我试图理解如何通过C 11扩展联合 . 一个改变的是能够使用现在非平凡的特殊成员函数的非静态数据成员 . 来自cppreference.com
如果一个union包含一个非平凡的特殊成员函数的非静态数据成员(默认构造函数,复制/移动构造函数,复制/移动赋值或析构函数),那么该函数在联合中默认被删除,需要由程序员明确定义 . 最多一个数据成员可以拥有默认成员初始值设定项 .
我正在尝试以下代码:
struct X
{
~X() {};
};
union U
{
X x;
~U() {};
};
int main()
{
U s1{}; // works, probably aggregate initialization
U s2; // DOES NOT compile, why?
}
这里 X (用作union的数据成员)有一个用户提供的析构函数,因此默认情况下会删除union的析构函数 . 因此我明确提供了一个 . 但是,代码无法编译,错误
注意:'U :: U()'被隐式删除,因为默认定义不正确:
如果我删除最后一行 U s2; ,代码将编译 .
Question 这里发生了什么?为什么 U s1{}; 编译,但 U s2; 没有?联合的默认ctor是否标记为已删除(如果是,为什么?!),并且在第一种情况下我们只是聚合初始化?请注意,如果我提供 U(){}; // not U() = default; 代码编译(但如果我只提供 X 的ctor,则不会) .
EDIT
在深入了解标准(N4527)之后:
Unions: 9.5/2 [class.union]
[注意:如果union的任何非静态数据成员具有非平凡的默认构造函数(12.1),复制构造函数(12.8),移动构造函数(12.8),复制赋值运算符(12.8),移动赋值运算符(12.8)或析构函数(12.4),联合的相应成员函数必须由用户提供,否则将为联合隐式删除(8.4.3) . -endnote]
这似乎是一个gcc bug(现在报道here) . 代码在clang和gcc 4.8.2或更早版本上编译,它在gcc4.9及更高版本上中断(感谢@ T.C . 指出) .
编译器:g 5.3, -std=c++11 使用 .