Re[11]: Багафича VS8?!!
От: Кодт Россия  
Дата: 09.06.07 12:02
Оценка:
Здравствуйте, <Аноним>, Вы писали:

P>>А "ненастоящие" это только те которые из обычных кастом получены

А>Нет. В основной массе это переданные через константную ссылку.
Это — считай, тот же каст. Неявный.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[9]: Багафича VS8?!!
От: Кодт Россия  
Дата: 09.06.07 12:02
Оценка:
Здравствуйте, 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., если до того не вылетим по защите памяти
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Багафича VS8?!!
От: Кодт Россия  
Дата: 09.06.07 12:06
Оценка: 1 (1) :))
Здравствуйте, Programador, Вы писали:

P>#include <math.h>
P>const int A::a=sin(0.);

В данном контексте sin() — это грех() .
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[10]: Багафича VS8?!!
От: elcste  
Дата: 09.06.07 14:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>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.
Re[10]: Багафича VS8?!!
От: Programador  
Дата: 09.06.07 19:23
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Например, если мы переделаем для числовых литералов,

К>
К>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 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой
Re[11]: Багафича VS8?!!
От: Programador  
Дата: 09.06.07 19:25
Оценка:
Здравствуйте, elcste, Вы писали:

E>Здравствуйте, Кодт, Вы писали:


E>Почему? Все это совершенно легальные действия. Что с built-in, что с user-defined types.

А что означает легальные действие применительно к user-defined types?
Re[8]: Багафича VS8?!!
От: Андрей Тарасевич Беларусь  
Дата: 10.06.07 16:00
Оценка: 1 (1)
Здравствуйте, 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.
Best regards,
Андрей Тарасевич
Re[11]: Багафича VS8?!!
От: Кодт Россия  
Дата: 13.06.07 07:57
Оценка:
Здравствуйте, Programador, Вы писали:

P>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой


Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.
Впрочем, я сейчас попробовал скомпилировать вот такой простой код
void trash(const double&); // пишет туда мусор
void crash(const double&); // читает мусор и валится

int main()
{
    trash(1.23);
    crash(1.23);
}

с разными опциями — но VC всегда копирует глобальную константу перед каждым вызовом.
Т.е.
const double xyz = 1.23;

int main()
{
    double tmp;
    
    tmp = xyz;
    trash(tmp);
    
    tmp = xyz;
    crash(tmp);
}

Боится
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[12]: Багафича VS8?!!
От: elcste  
Дата: 13.06.07 08:33
Оценка: 52 (1)
Здравствуйте, Кодт, Вы писали:

К>Впрочем, я сейчас попробовал скомпилировать вот такой простой код

К>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.


Ничто в стандарте не запрещает модифицировать этот временный объект.
Re[13]: Багафича VS8?!!
От: Кодт Россия  
Дата: 13.06.07 08:47
Оценка:
Здравствуйте, 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>Ничто в стандарте не запрещает модифицировать этот временный объект.


И как я понимаю, абсолютно без разницы — встроенный тип или нет.

Тогда уточняющий вопрос, чтобы сомнений вообще не было
const int* pint(const int& x) { return x; }

int main()
{
    assert( pint(1) != pint(1) );
}

Поскольку в обоих подвыражениях созданы временные объекты, то адреса у них должны (а не просто могут) быть разными? И компилятор не вправе сэкономить.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[14]: Багафича VS8?!!
От: elcste  
Дата: 13.06.07 09:17
Оценка:
Здравствуйте, Кодт, Вы писали:

К>И как я понимаю, абсолютно без разницы — встроенный тип или нет.

К>Тогда уточняющий вопрос, чтобы сомнений вообще не было
К>const int* pint(const int& x) { return &x; }

К>int main()
К>{
К>    assert( pint(1) != pint(1) );
К>}

К>Поскольку в обоих подвыражениях созданы временные объекты, то адреса у них должны (а не просто могут) быть разными? И компилятор не вправе сэкономить.

Да, это хоть и временные, а разные объекты, и адреса у них должны быть различны. По-моему, единственное исключение из этого правила сделано для строковых литералов, и оно оговорено явно (2.13.4/2).
Re[12]: Багафича VS8?!!
От: Programador  
Дата: 14.06.07 16:39
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Programador, Вы писали:


P>>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой


К>Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.


Нашей целью является релиз (по крайней мере в некоторых случаях). Тогда зачем нужен дебаг? Дебагинфо и повторенные куски кода и мертвый код (if(zero_expression){...} ) это должно быть, но зачем багги маскировать? Не очень както логично у МС помоему, я хочу теже баги что что в релизе. А то отлаживается всегда совсем не то что отдается заказчику

if(a)
 {  b=1; // этот код задублирова в режиме отладки
    ........
 }
else
 {  b=1; // в релизе можно вынести вперед
    ........
 }
Re[13]: Багафича VS8?!!
От: Кодт Россия  
Дата: 14.06.07 17:35
Оценка:
Здравствуйте, Programador, Вы писали:

P>>>не вижу разницы между целым и плавающим. VC6 для обоих в стеке завел копии. Покрайней мере в дебаге, а в данном слугае сделать в дебаге по другому чем в релизе былобы крайней подлянкой


К>>Делать в дебаге и релизе по-разному — это не подлянка, а оптимизация.


P>Нашей целью является релиз (по крайней мере в некоторых случаях). Тогда зачем нужен дебаг? Дебагинфо и повторенные куски кода и мертвый код (if(zero_expression){...} ) это должно быть, но зачем багги маскировать? Не очень както логично у МС помоему, я хочу теже баги что что в релизе. А то отлаживается всегда совсем не то что отдается заказчику


Не программист if(zero_expression), а компилятор — может и должен делать разный код.
Да, в некоторых случаях это приводит к неприятностям.

1) Главный источник неприятностей — это неопределённое и неспецифицированное поведение. Например, закладываться на порядок вызова частей выражения.
2) Далее, разница в дебажных и релизных версиях библиотек. Например, закладываться на якобы известные размеры типов (в дебажной версии STL итератор вектора может быть классом, а в релизной — указателем, и т.п.)
3) Плавающая арифметика. В зависимости от опций компилятора, а уж тем более от порядка вычислений, результат может варьироваться. А превратить вычислительную погрешность в катастрофу — дело нехитрое.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.