与const和nonconst成员的联合?

时间:2021-05-06 05:29:12

This appears to be undefined behavior

这似乎是未定义的行为

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

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

The spec says

规范说

Creating a new object at the storage location that a const object with static, thread, or automatic storage duration occupies or, at the storage location that such a const object used to occupy before its lifetime ended results in undefined behavior.

在存储位置创建一个具有静态,线程或自动存储持续时间的const对象占用的新对象,或者在此生成对象在其生命周期结束之前占用的存储位置处导致未定义的行为。

But no compiler warns me while it's an easy to diagnose mistake. Am I misinterpreting the wording?

但是没有编译器警告我,因为它很容易诊断错误。我误解了措辞吗?

3 个解决方案

#1


7  

The latest C++0x draft standard is explicit about this:

最新的C ++ 0x草案标准是明确的:

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

在联合中,至多一个非静态数据成员可以在任何时间处于活动状态,也就是说,至多一个非静态数据成员的值可以随时存储在并集中。

So your statement

所以你的陈述

a.y = 1;

is fine, because it changes the active member from x to y. If you subsequently referenced a.x as an rvalue, the behaviour would be undefined:

很好,因为它将活动成员从x更改为y。如果您随后将a.x引用为右值,则行为将是未定义的:

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

Your quote from the spec is not relevant here, because you are not creating any new object.

您在此处引用的引用与此无关,因为您没有创建任何新对象。

#2


1  

If it's any consolation - the Microsoft Xbox 360 compiler (which is based on Visual Studio's compiler) does error out. Which is funny, because that's usually the most lenient of the bunch.

如果它是任何安慰 - 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

This error goes away if I take the const away. gcc-based compilers don't complain.

如果我取走const,这个错误就会消失。基于gcc的编译器不会抱怨。

EDIT: The Microsoft Visual C++ compiler has the same warning.

编辑:Microsoft Visual C ++编译器具有相同的警告。

#3


1  

It doesn't really make sense to have a const member of a union, and I'm surprised that the standard allows it. The purpose of all of the many limitations on what can go into a union is to arrive at a point where bitwise assignment will be a valid assignment operator for all members, and you can't use bitwise assignment to assign to a const int. My guess is that it's just a case that no one had previously thought of (although it affects C as well as C++, so it's been around for awhile).

拥有一个联盟的const成员并没有多大意义,我很惊讶标准允许它。可以进入联合的所有许多限制的目的是达到一个点,其中按位赋值将是所有成员的有效赋值运算符,并且您不能使用按位赋值来赋值给const。我的猜测是,这只是一个没有人曾经想过的情况(虽然它影响C和C ++,所以它已经存在了一段时间)。

#1


7  

The latest C++0x draft standard is explicit about this:

最新的C ++ 0x草案标准是明确的:

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

在联合中,至多一个非静态数据成员可以在任何时间处于活动状态,也就是说,至多一个非静态数据成员的值可以随时存储在并集中。

So your statement

所以你的陈述

a.y = 1;

is fine, because it changes the active member from x to y. If you subsequently referenced a.x as an rvalue, the behaviour would be undefined:

很好,因为它将活动成员从x更改为y。如果您随后将a.x引用为右值,则行为将是未定义的:

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

Your quote from the spec is not relevant here, because you are not creating any new object.

您在此处引用的引用与此无关,因为您没有创建任何新对象。

#2


1  

If it's any consolation - the Microsoft Xbox 360 compiler (which is based on Visual Studio's compiler) does error out. Which is funny, because that's usually the most lenient of the bunch.

如果它是任何安慰 - 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

This error goes away if I take the const away. gcc-based compilers don't complain.

如果我取走const,这个错误就会消失。基于gcc的编译器不会抱怨。

EDIT: The Microsoft Visual C++ compiler has the same warning.

编辑:Microsoft Visual C ++编译器具有相同的警告。

#3


1  

It doesn't really make sense to have a const member of a union, and I'm surprised that the standard allows it. The purpose of all of the many limitations on what can go into a union is to arrive at a point where bitwise assignment will be a valid assignment operator for all members, and you can't use bitwise assignment to assign to a const int. My guess is that it's just a case that no one had previously thought of (although it affects C as well as C++, so it's been around for awhile).

拥有一个联盟的const成员并没有多大意义,我很惊讶标准允许它。可以进入联合的所有许多限制的目的是达到一个点,其中按位赋值将是所有成员的有效赋值运算符,并且您不能使用按位赋值来赋值给const。我的猜测是,这只是一个没有人曾经想过的情况(虽然它影响C和C ++,所以它已经存在了一段时间)。