C++11中的并集:默认构造函数似乎已被删除

Unions in C++11: default constructor seems to be deleted

本文关键字:删除 构造函数 默认 C++11      更新时间:2023-10-16

我正在努力了解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的默认构造函数将被删除。

相关文章: