Союз с const и неконстантным членом? - PullRequest
21 голосов
/ 13 апреля 2011

Похоже, что это неопределенное поведение

union A {
  int const x;
  float y;
};

A a = { 0 };
a.y = 1;

В спецификации сказано:

Создание нового объекта в месте хранения, которое занимает const-объект со статическим, потоковым или автоматическим продолжением хранения, или в месте хранения, которое такой объект const занимал до того, как закончился срок его службы, приводит к неопределенному поведению. *

Но ни один компилятор не предупреждает меня, пока легко диагностировать ошибку. Я неправильно понимаю формулировку?

Ответы [ 3 ]

7 голосов
/ 13 апреля 2011

В последнем проекте стандарта C ++ 0x об этом явно сказано:

В объединении максимум один из нестатических элементов данных может быть активным на любом время, то есть значение не более одного из нестатических элементов данных может храниться в союзе в любое время.

Итак, ваше заявление

a.y = 1;

хорошо, потому что он изменяет активный член с x на y. Если впоследствии вы ссылаетесь на a.x как на значение, поведение будет неопределенным:

cout << a.x << endl ; // Undefined!

Ваша цитата из спецификации здесь не актуальна, потому что вы не создаете новый объект.

2 голосов
/ 13 апреля 2011

Не имеет смысла иметь const член union, и я удивлен, что стандарт это позволяет. Целью всех многочисленных ограничений того, что может входить в union, является достижение точки, где побитовое присваивание будет действительным оператором присваивания для всех членов, и вы не можете использовать побитовое присваивание для присваивания * 1004. *. Я предполагаю, что это просто тот случай, о котором раньше никто не задумывался (хотя он влияет на C так же, как и на C ++, так что это уже давно).

1 голос
/ 13 апреля 2011

Если это утешит - компилятор Microsoft Xbox 360 (основанный на компиляторе Visual Studio) выдает ошибку.Что забавно, потому что это обычно самый снисходительный из всех.

error C2220: warning treated as error - no 'object' file generated
warning C4510: 'A' : default constructor could not be generated
    : see declaration of 'A'
warning C4610: union 'A' can never be instantiated - user defined constructor required

Эта ошибка исчезнет, ​​если я уберу const.Компиляторы на основе gcc не жалуются.

РЕДАКТИРОВАТЬ: Компилятор Microsoft Visual C ++ имеет то же предупреждение.

...