C++11中的并集:默认构造函数似乎已被删除
Unions in C++11: default constructor seems to be deleted
我正在努力了解C++11是如何扩展并集的。改变的一点是,现在可以使用非静态数据成员和非琐碎的特殊成员函数。来自cppreference.com
如果并集包含一个具有非平凡特殊成员函数(默认构造函数、复制/移动构造函数、拷贝/移动赋值或析构函数)的非静态数据成员,则该函数在并集中默认会被删除,并且需要由程序员显式定义。最多一个数据成员可以具有默认的成员初始值设定项。
我正在尝试以下代码:
struct X
{
~X() {};
};
union U
{
X x;
~U() {};
};
int main()
{
U s1{}; // works, probably aggregate initialization
U s2; // DOES NOT compile, why?
}
在Coliru上直播
这里X
(用作并集的数据成员)有一个用户提供的析构函数,因此默认情况下会删除并集的析构因子。因此,我明确提供了一个。然而,代码无法编译,出现错误
注意:"U::U()"被隐式删除,因为默认定义格式不正确:
如果删除最后一行U s2;
,代码就会编译。
问题这里发生了什么?为什么U s1{};
会编译,而U s2;
不会?联合的默认ctor是否标记为已删除(如果是,为什么?!),而在第一种情况下,我们只进行聚合初始化?注意,如果我提供U(){}; // not U() = default;
,代码就会编译(但如果我只提供X
的ctor,则不会编译)。
编辑
在深入研究标准(N4527)后:
工会:9.5/2[阶级工会]
[注意:如果并集的任何非静态数据成员都有一个非平凡的默认构造函数(12.1)、复制构造函数(12.8)、移动构造函数(12.8)、复制赋值运算符(12.8
这似乎是一个gcc错误(现在在这里报告)。该代码在clang和gcc 4.8.2或更早版本上编译,在gcc4.9及更高版本上中断(感谢@T.C.的指出)。
编译器:g++5.3,使用-std=c++11
。
X不是pod类型,因为它具有析构函数,所以不可复制U也不是吊舱类型。
U s2;
尝试调用已删除的默认构造函数,因此错误
U s1 {};
使用成员方式初始化,不要调用任何costructor
在与非pod成员的联合中,联合的默认构造函数被删除,因为它会调用成员的默认构造函数,即编译器不知道该调用哪个成员的默认重构器
Union XX{
string m1;
vector <int> m2;
}
XX的默认构造函数不能调用m1和m2的默认构造函数,因此它被删除
cppreference引号不清楚。发生的情况是,如果联合的ANY成员定义了这些非平凡的特殊成员函数的ANY,那么它们中的1LL将在联合中默认删除。
因此,由于X
有一个非平凡的析构函数,因此U
的默认构造函数将被删除。
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- std::ofstream 作为类成员删除复制构造函数?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- C++ 尝试在不存在的构造函数中引用已删除的函数(使用 rapidJson)
- 具有已删除移动和复制构造函数的类的就地构造
- 聚合初始化和删除的复制构造函数,也称为不可复制的 obejcts 作为字段
- 在引用初始化中使用已删除的复制构造函数进行复制初始化
- 在运行时有条件地删除类成员或跳过调用该成员对象的构造函数
- 我的类中几乎所有的构造函数和解构函数都被隐式定义为已删除?
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 调用类模板中隐式删除的复制构造函数
- 当类型适当的构造函数可用时,为什么一个编译器尝试使用已删除的副本构造函数
- 不带初始值设定项的构造函数列表,其中包含带有已删除构造函数的对象
- 是否可以实例化具有已删除构造函数和析构函数的非聚合类?
- 为什么编译器在试图初始化具有C 11样式的对象数组时隐含删除构造函数
- 调用的已删除构造函数
- 为什么要显式删除构造函数而不是将其设为私有?
- 如何创建此已标记联合的实例?关于已删除构造函数的编译器错误