Здравствуйте, Аноним, Вы писали:
А>Почему всплывает exception? Это как то отражено в стандарте?
А>
А>struct A {
А> void f(int aa) { const_cast<int&>(a)=aa;}
А> static const int a;
А>};
А>const int A::a=0;
А>int main() {
А> A a;
А> int b(0);
А> a.f(b);
А>}
А>
В стандарте говорится, что в этом случае будет UB. (ссылку искать лениво)
С точки зрения компилятора: ты объявил константу, компилятор положил ее в
readonly память. А теперь ты пытаешься туда лезть? Что ему делать, если память RO?
С уважением, Александр
Re: Багафича VS8?!!
От:
Аноним
Дата:
08.06.07 10:31
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Почему всплывает exception? Это как то отражено в стандарте?
А>
А>struct A {
А> void f(int aa) { const_cast<int&>(a)=aa;}
А> static const int a;
А>};
А>const int A::a=0;
А>int main() {
А> A a;
А> int b(0);
А> a.f(b);
А>}
А>
Так работает:
struct A {
void f(int aa) { const_cast<int&>(a)=aa;}
static int a;
};
int A::a=0;
int main() {
A a;
int b(0);
a.f(b);
}
странно... может, находится в read-only сегменте данных..
Здравствуйте, Smal, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Аноним, Вы писали:
А>>>Почему всплывает exception? Это как то отражено в стандарте?
А>>>
А>>>struct A {
А>>> void f(int aa) { const_cast<int&>(a)=aa;}
А>>> static const int a;
А>>>};
А>>>const int A::a=0;
А>>>int main() {
А>>> A a;
А>>> int b(0);
А>>> a.f(b);
А>>>}
А>>>
А>>Так работает: А>>struct A { А>> void f(int aa) { const_cast<int&>(a)=aa;} А>> static int a; А>>}; А>>int A::a=0;
А>>int main() { А>> A a; А>> int b(0); А>> a.f(b); А>>}
А>>странно... может, находится в read-only сегменте данных.. А>>
S>Ничего странного в этом нет.
Здравствуйте, Smal, Вы писали:
S>Здравствуйте, shnyaps, Вы писали:
А>>>>странно... может, находится в read-only сегменте данных.. А>>>>
S>>>Ничего странного в этом нет.
S>>Почему тогда?
S>здесь
Здравствуйте, shnyaps, Вы писали:
S>а можно ссыдку на стандарт?
7.1.5.1/4
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.
B>7.1.5.1/4
B>Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
B>object during its lifetime (3.8) results in undefined behavior.
B>В 7.1.5.1/5 есть пример.
И как это понимать? Получается любой!!! const_cast — UB
Re[7]: Багафича VS8?!!
От:
Аноним
Дата:
08.06.07 12:33
Оценка:
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, shnyaps, Вы писали:
S>>а можно ссыдку на стандарт?
B>
B>7.1.5.1/4
B>Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
B>object during its lifetime (3.8) results in undefined behavior.
B>В 7.1.5.1/5 есть пример.
Спасибо.
Получается для того, чтобы воспользоваться const_cast ты должен быть уверен в том, что он
ссылается на не константный тип, иначу UB. Я правильно понимаю??
Re: Багафича VS8?!!
От:
Аноним
Дата:
08.06.07 12:43
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Почему всплывает exception? Это как то отражено в стандарте?
А>
А>struct A {
А> void f(int aa) { const_cast<int&>(a)=aa;}
А> static const int a;
А>};
А>const int A::a=0;
А>int main() {
А> A a;
А> int b(0);
А> a.f(b);
А>}
А>
Одного не пойму, зачем нужно присваивать ссылку на переменную размещенную в стеке (aa) статической (a).
Здравствуйте, Аноним, Вы писали:
А>Спасибо. А>Получается для того, чтобы воспользоваться const_cast ты должен быть уверен в том, что он А>ссылается на не константный тип, иначу UB. Я правильно понимаю??
const_cast-ом можно пользоваться всегда, а вот модифицировать объект, ссылка на который получена с помощью const_cast, можно только в том случае, если мы имеем дело с неконстантным объектом.
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, Bell, Вы писали:
B>>
B>>7.1.5.1/4
B>>Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
B>>object during its lifetime (3.8) results in undefined behavior.
B>>В 7.1.5.1/5 есть пример.
P>И как это понимать? Получается любой!!! const_cast — UB
Нет, не любой. К UB ведет снятие константности и модификация "настоящих" констант.
Здравствуйте, Bell, Вы писали:
P>>И как это понимать? Получается любой!!! const_cast — UB B>Нет, не любой. К UB ведет снятие константности и модификация "настоящих" констант.
А "ненастоящие" это только те которые из обычных кастом получены
Здравствуйте, Аноним, Вы писали:
А>сдается мне, что static const для встроенных типов объявленных в классах — костанты времени компиляции.. выводы делаем сами
Да повсякому. Если const int A::a=0; впереди main то времени компиляции, а если позади то рунтайм. Инициализация через функцию переводит в записываемый сегмент
Здравствуйте, <Аноним>, Вы писали:
P>>А "ненастоящие" это только те которые из обычных кастом получены А>Нет. В основной массе это переданные через константную ссылку.
Это — считай, тот же каст. Неявный.
Здравствуйте, Bell, Вы писали:
B>const_cast-ом можно пользоваться всегда, а вот модифицировать объект, ссылка на который получена с помощью const_cast, можно только в том случае, если мы имеем дело с неконстантным объектом.
А кстати, как разруливается ситуация:
struct Foo
{
int x;
Foo() : x(0) {}
Foo& get() { return *this; }
void bar() { ++x; }
};
void run(Foo& f) { f.bar(); }
void runc(const Foo& f) { run(const_cast<Foo&>(f)); }
int main()
{
Foo().bar(); // можно
run(Foo()); // нельзя
run(Foo().get()); // можно
runc(Foo()); // хак
}
В первом и третьем случае мы явно используем преобразование неконстантного rvalue к неконстантному же lvalue — в тех рамках, которые оговорены Стандартом.
В четвёртом — по факту, делаем то же самое. Но может быть, компилятор вправе сделать какие-то допущения: в том месте, где rvalue существует, его неконстантность не востребована, и следовательно, можно попробовать разместить его в секции констант или ещё какой трюк применить?
Например, если мы переделаем для числовых литералов,
void runci(const int& x) { const_cast<int&>(x)=0; }
void runcf(const double& x) { const_cast<double&>(x)=0.; }
int main()
{
runci(rand()); // здесь будет по-настоящему временное значение, стреляй-не хочу
runci(1); // здесь - как компилятору бог на душу положит
runcf(1.); // а вот здесь - точно расстрел статической константы (особенность интеловских архитектур)double x = 1.; // можем внезапно получить 0., если до того не вылетим по защите памяти
}
К>int main()
К>{
К> Foo().bar(); // можно
К> run(Foo()); // нельзя
К> run(Foo().get()); // можно
К> runc(Foo()); // хак
К>}
К>
К>В первом и третьем случае мы явно используем преобразование неконстантного rvalue к неконстантному же lvalue — в тех рамках, которые оговорены Стандартом. К>В четвёртом — по факту, делаем то же самое. Но может быть, компилятор вправе сделать какие-то допущения: в том месте, где rvalue существует, его неконстантность не востребована, и следовательно, можно попробовать разместить его в секции констант или ещё какой трюк применить?
К>Например, если мы переделаем для числовых литералов,
К>void runci(const int& x) { const_cast<int&>(x)=0; }
К>void runcf(const double& x) { const_cast<double&>(x)=0.; }
К>int main()
К>{
К> runci(rand()); // здесь будет по-настоящему временное значение, стреляй-не хочу
К> runci(1); // здесь - как компилятору бог на душу положит
К> runcf(1.); // а вот здесь - точно расстрел статической константы (особенность интеловских архитектур)
К> double x = 1.; // можем внезапно получить 0., если до того не вылетим по защите памяти
К>}
Почему? Все это совершенно легальные действия. Что с built-in, что с user-defined types.
Здравствуйте, Кодт, Вы писали:
К>Например, если мы переделаем для числовых литералов, К>
К>void runci(const int& x) { const_cast<int&>(x)=0; }
К>void runcf(const double& x) { const_cast<double&>(x)=0.; }
К>int main()
К>{
К> runci(rand()); // здесь будет по-настоящему временное значение, стреляй-не хочу
К> runci(1); // здесь - как компилятору бог на душу положит
К> runcf(1.); // а вот здесь - точно расстрел статической константы (особенность интеловских архитектур)
К> double x = 1.; // можем внезапно получить 0., если до того не вылетим по защите памяти
К>}
К>
не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой
Здравствуйте, elcste, Вы писали:
E>Здравствуйте, Кодт, Вы писали:
E>Почему? Все это совершенно легальные действия. Что с built-in, что с user-defined types.
А что означает легальные действие применительно к user-defined types?
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, Bell, Вы писали:
B>>
B>>7.1.5.1/4
B>>Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
B>>object during its lifetime (3.8) results in undefined behavior.
B>>В 7.1.5.1/5 есть пример.
P>И как это понимать? Получается любой!!! const_cast — UB
Нет. Получается, что сам 'const_cast' — никогда не UB. А вот собственно попытка модификации неконстантного обьъекта через полученный при помощи 'const_cast' указатель — это уже UB.
Здравствуйте, Programador, Вы писали:
P>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой
Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.
Впрочем, я сейчас попробовал скомпилировать вот такой простой код
void trash(const double&); // пишет туда мусорvoid crash(const double&); // читает мусор и валитсяint main()
{
trash(1.23);
crash(1.23);
}
с разными опциями — но VC всегда копирует глобальную константу перед каждым вызовом.
Т.е.
Здравствуйте, Кодт, Вы писали:
К>Впрочем, я сейчас попробовал скомпилировать вот такой простой код
К>void trash(const double&); // пишет туда мусор
К>void crash(const double&); // читает мусор и валится
К>int main()
К>{
К> trash(1.23);
К> crash(1.23);
К>}
К>с разными опциями — но VC всегда копирует глобальную константу перед каждым вызовом.
К>Боится
Просто соответствует стандарту. В порядке исключения.
Когда rvalue встроенного типа привязывается к ссылке, создается временный объект и инициализируется значением rvalue. К этому временному объекту и привязывается ссылка.
8.5.3/5 — Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy initialization (8.5). The reference is then bound to the temporary.
Ничто в стандарте не запрещает модифицировать этот временный объект.
Здравствуйте, elcste, Вы писали:
E>Когда rvalue встроенного типа привязывается к ссылке, создается временный объект и инициализируется значением rvalue. К этому временному объекту и привязывается ссылка. E>
8.5.3/5 — Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy initialization (8.5). The reference is then bound to the temporary.
E>Ничто в стандарте не запрещает модифицировать этот временный объект.
И как я понимаю, абсолютно без разницы — встроенный тип или нет.
Тогда уточняющий вопрос, чтобы сомнений вообще не было
Здравствуйте, Кодт, Вы писали:
К>И как я понимаю, абсолютно без разницы — встроенный тип или нет. К>Тогда уточняющий вопрос, чтобы сомнений вообще не было
К>Поскольку в обоих подвыражениях созданы временные объекты, то адреса у них должны (а не просто могут) быть разными? И компилятор не вправе сэкономить.
Да, это хоть и временные, а разные объекты, и адреса у них должны быть различны. По-моему, единственное исключение из этого правила сделано для строковых литералов, и оно оговорено явно (2.13.4/2).
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Programador, Вы писали:
P>>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой
К>Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.
Нашей целью является релиз (по крайней мере в некоторых случаях). Тогда зачем нужен дебаг? Дебагинфо и повторенные куски кода и мертвый код (if(zero_expression){...} ) это должно быть, но зачем багги маскировать? Не очень както логично у МС помоему, я хочу теже баги что что в релизе. А то отлаживается всегда совсем не то что отдается заказчику
if(a)
{ b=1; // этот код задублирова в режиме отладки
........
}
else
{ b=1; // в релизе можно вынести вперед
........
}
Здравствуйте, Programador, Вы писали:
P>>>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой
К>>Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.
P>Нашей целью является релиз (по крайней мере в некоторых случаях). Тогда зачем нужен дебаг? Дебагинфо и повторенные куски кода и мертвый код (if(zero_expression){...} ) это должно быть, но зачем багги маскировать? Не очень както логично у МС помоему, я хочу теже баги что что в релизе. А то отлаживается всегда совсем не то что отдается заказчику
Не программист if(zero_expression), а компилятор — может и должен делать разный код.
Да, в некоторых случаях это приводит к неприятностям.
1) Главный источник неприятностей — это неопределённое и неспецифицированное поведение. Например, закладываться на порядок вызова частей выражения.
2) Далее, разница в дебажных и релизных версиях библиотек. Например, закладываться на якобы известные размеры типов (в дебажной версии STL итератор вектора может быть классом, а в релизной — указателем, и т.п.)
3) Плавающая арифметика. В зависимости от опций компилятора, а уж тем более от порядка вычислений, результат может варьироваться. А превратить вычислительную погрешность в катастрофу — дело нехитрое.