我看了http://www.stroustrup.com/C++11FAQ.html#unions
但是我无法编译给定的例子:
union U1 {
int m1;
complex<double> m2; // ok
};
union U2 {
int m1;
string m3; // ok
};
U1 u; // ok
u.m2 = {1,2}; // ok: assign to the complex member
结果:
main.cpp:85:8: error: use of deleted function 'U1::U1()'
U1 u; // ok
^
main.cpp:75:11: note: 'U1::U1()' is implicitly deleted because the default definition would be ill-formed:
union U1 {
^
main.cpp:77:25: error: union member 'U1::m2' with non-trivial 'constexpr std::complex<double>::complex(double, double)'
complex<double> m2; // ok
^
main.cpp:86:5: error: 'u' does not name a type
u.m2 = {1,2}; // ok: assign to the complex member
^
make: *** [main.o] Error 1
问题:
我认为在非限制联合中,如果没有手动给出默认构造函数,则将构造第一个元素。这是真的,如何写一个有效的例子?
以下也不会编译:
class Y
{
public:
constexpr Y() {}
};
union X
{
int a;
float b;
Y x;
//X(){}
};
X x;
int main(){}
相同的错误消息:
main.cpp:112:7: error: use of deleted function 'X::X()'
X x;
^
main.cpp:104:11: note: 'X::X()' is implicitly deleted because the default definition would be ill-formed:
union X
^
main.cpp:108:11: error: union member 'X::x' with non-trivial 'constexpr Y::Y()'
Y x;
^
make: *** [main.o] Error 1
答案 0 :(得分:5)
在标准中,第2段(注释中)中的[class.union]提及说明了这一点:
union可以有成员函数(包括构造函数和 析构函数),但不是虚函数(10.3)。工会不应该有 基类。联合不得用作基类。如果一个工会 包含程序所引用的非静态数据成员 病态的。最多一个联盟的非静态数据成员可能有一个 大括号或相等的初始值设定。 [注意:如果有任何非静态数据成员 union有一个非平凡的默认构造函数(12.1),复制构造函数 (12.8),移动构造函数(12.8),复制赋值运算符(12.8),移动 赋值运算符(12.8),或析构函数(12.4),对应的 union的成员函数必须是用户提供的,否则就是 隐含删除(8.4.3)联盟。 - 结束说明]
由于您的类具有not-default构造函数,因此编译失败。
第3段甚至提供了一个例子:
union U {
int i;
float f;
std::strings;
};
并说:
由于std :: string(21.3)声明了所有特殊成员函数的非平凡版本,因此U将具有隐式删除的默认构造函数,复制/移动构造函数,复制/移动赋值运算符和析构函数。要使用U,必须由用户提供部分或全部这些成员函数。
Bjarne写了同样的话:
如果union具有带有用户定义的构造函数,复制或析构函数的成员,则删除该特殊函数;也就是说,它不能用于union类型的对象。这是新的。
但错误的例子。 std::string
和std::complex
都有非默认构造函数。因此,拥有这些的工会需要工会的构造函数。
答案 1 :(得分:0)
问题是联盟中存在m2
。因为complex具有“用户定义的”构造函数,所以包含它的union的构造函数是deleted
。
“如果联合具有带有用户定义的构造函数,复制操作,移动操作或析构函数的成员,则会删除该联合的特殊函数; 也就是说,它不能用于联合类型的对象。“,”C ++编程语言“,第215页。
union U { int m1;
complex<double> m2; // complex has a constructor
string m3; // string has a constructor (maintaining a serious invariant)
};
“幸运的是U不会编译。” (同一参考)