使用此代码:
struct A
{
int i;
const int b;
};
// The union is to verify that A is a type that can be used in a union.
union U
{
A a;
int b;
};
int main()
{
U a = {1, 1};
U b = {2, 1};
}
g ++版本4.8.3抱怨错误:
a.cpp:9:4: error: member ‘A U::a’ with copy assignment operator not allowed in union
A a;
^
a.cpp:9:4: note: unrestricted unions only available with -std=c++11 or -std=gnu++11
但clang 3.5.0编译此代码时没有错误。哪一个是正确的?这是编译器错误吗?
我尝试解决这个问题:
从C ++ 03标准第9.5节第1段:
在联合中,最多一个数据成员可以随时处于活动状态,也就是说,任何时候最多一个数据成员的值都可以存储在一个联合中。 [注意:为了简化联合的使用,我们做了一个特别的保证:如果一个POD-union包含几个共享一个公共初始序列的POD结构(9.2),并且这个POD-union类型的一个对象包含一个在POD结构中,允许检查任何POD结构成员的共同初始序列;见9.2。 ] union的大小足以包含其最大的数据成员。每个数据成员都被分配,就好像它是结构的唯一成员一样。联合可以具有成员函数(包括构造函数和析构函数),但不具有虚函数(10.3)。工会不得有基类。联合不得用作基类。 具有非平凡构造函数(12.1)的类的对象,非平凡的复制构造函数(12.8),非平凡的析构函数(12.4)或非平凡的复制赋值运算符(13.5.3, 12.8)不能是联盟的成员,也不能是这类对象的数组。如果联合包含静态数据成员或引用类型的成员,则该程序格式不正确。
从C ++ 03标准第12.8节第10和第11段:
如果类定义没有显式声明一个复制赋值运算符,则会隐式声明一个。如果X的每个直接基类B都有一个复制赋值运算符,其参数类型为const B&,const volatile B& S,则X类的隐式声明的复制赋值运算符将具有
X& X::operator=(const X&)
形式。对于类型为M(或其数组)的X的所有非静态数据成员,每个这样的类类型都有一个复制赋值运算符,其参数类型为const M&,const volatile M&或者M。
Otherwise, the implicitly declared copy assignment operator will have the form X& X::operator=(X&)
...如果隐式声明类X并且类X没有虚函数(10.3)且没有虚基类(10.1),则类X的复制赋值运算符是微不足道的,并且每个X的直接基类都有一个简单的复制赋值运算符,对于类类型(或其数组)的X的所有非静态数据成员,每个这样的类类型都有一个普通的复制赋值运算符;否则复制赋值运算符是非常重要的。
我不确定哪个编译器是正确的,因为我不知道常量成员是否有一个普通的复制赋值运算符。
修改 编译命令是:
clang++ a.cpp -o a
g++ a.cpp -o a
EDIT2:
为了表明g ++不抱怨A :: b为const
但A没有构造函数,我也试过这个程序:
struct A
{
int i;
const int b;
};
int main()
{
A a = {1, 1};
}
这在g ++和clang ++上编译时没有错误:
g++ b.cpp -o b
clang++ b.cpp -o b
答案 0 :(得分:4)
正如您正确指出的那样,复制赋值运算符隐式声明并且是微不足道的。 默认构造函数也是如此,它也是微不足道的并且是隐式声明的。
请注意,这两个成员函数都没有隐式定义 - 只有在使用它们时才会发生,[class.ctor] / 7:
类的隐式声明的默认构造函数是隐式 在用于创建类类型(1.8)的对象时定义。
..这显然不是这种情况。
这是关键区别,@ dasblinkenlight引用的原因与此事无关:默认构造函数从未定义,因此缺少 mem-initializer-id 的段落s不适用。
如何连接const
成员和赋值运算符?这里:
隐式声明的复制赋值运算符是隐式定义的 当为其类类型的对象分配其类类型的值或从其类类型派生的类类型的值时强> 如果复制分配的类,则程序格式不正确 运算符隐含已定义具有:
const
类型的非静态数据成员,或[..]
因此,如果使用复制赋值运算符,程序将是错误的。但它不是。所有特殊成员函数都是单独声明的,对非静态数据成员的const
的任何限制仅适用于隐式定义的特殊成员函数。
举个例子,拿
struct A
{
int i;
const int b;
};
int main()
{
A a = {1, 1};
}
哪个compiles fine under GCC。您的计划也应该是格式良好的,因为A
符合工会成员特殊成员职能的所有要求。