这似乎是未定义的行为
union A {
int const x;
float y;
};
A a = { 0 };
a.y = 1;
规范说
在存储位置创建一个具有静态,线程或自动存储持续时间的const对象占用的新对象,或者在这个const对象在其生命周期结束之前占用的存储位置导致未定义的行为。
但是没有编译器警告我,因为这是一个容易诊断的错误。我是否误解了措辞?
答案 0 :(得分:7)
最新的C ++ 0x草案标准明确指出:
在联合中,最多只有一个非静态数据成员可以在任何时候处于活动状态 时间,即至多一个非静态数据成员的值即可 随时存放在工会中。
所以你的陈述
a.y = 1;
很好,因为它会将有效成员从x
更改为y
。如果您随后将a.x
引用为右值,则行为将是未定义的:
cout << a.x << endl ; // Undefined!
您在此处引用的引用与此无关,因为您没有创建任何新对象。
答案 1 :(得分:1)
如果有任何安慰 - 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 ++编译器具有相同的警告。
答案 2 :(得分:1)
拥有const
的{{1}}成员并没有多大意义,我很惊讶标准允许它。可以进入union
的所有限制的目的是达到一个点,其中按位赋值将是所有成员的有效赋值运算符,并且您不能使用按位赋值来分配给union
。我的猜测是,这只是一个没有人曾经想过的情况(尽管它影响C和C ++,所以它已经存在了一段时间)。