vso*_*tco 11 c++ unions language-lawyer c++11
我试图理解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?
}
Run Code Online (Sandbox Code Playgroud)
这里X
(用作union的数据成员)有一个用户提供的析构函数,因此默认情况下会删除union的析构函数.因此我明确提供了一个.但是,代码无法编译,错误
注意:'U :: U()'被隐式删除,因为默认定义不正确:
如果我删除最后一行,代码将编译U s2;
.
问题这里发生了什么?为什么U s1{};
编译,但U s2;
不是?联合的默认ctor是否标记为已删除(如果是,为什么?!),并且在第一种情况下我们只是聚合初始化?请注意,如果我提供U(){}; // not U() = default;
代码编译(但不是如果我只提供代码X
).
编辑
在深入了解标准(N4527)之后:
工会:9.5/2 [class.union]
[注意:如果union的任何非静态数据成员具有非平凡的默认构造函数(12.1),复制构造函数(12.8),移动构造函数(12.8),复制赋值运算符(12.8),移动赋值运算符(12.8),或者析构函数(12.4),联合的相应成员函数必须是用户提供的,否则将为联合隐式删除(8.4.3).-endnote]
似乎这是一个错误的gcc(现报在这里).代码在clang和gcc 4.8.2或更早版本上编译,它在gcc4.9及更高版本上中断(感谢@TC指出).
编译器:g ++ 5.3,-std=c++11
使用.
cppreference 引用不清楚。发生的情况是,如果联合体的任何成员定义了任何这些重要的特殊成员函数,那么默认情况下,所有这些成员函数都将在联合体中被删除。
因此,由于您有一个不平凡的析构函数X
,因此U
默认构造函数被删除。