为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译

Why does a struct, that has another struct wrapped in a union as a member not compile without an explicit default constructor?

本文关键字:结构 封装 编译 不能 成员 默认 构造函数 为什么 情况下 另一个      更新时间:2023-10-16

这就是我所说的关系:

struct A{
int i = 1;
};
struct B{
union{A a;};
};
void main(){
B b;
};

在这个星座中,我的编译器(vs2015(抱怨BB::B(void)的默认构造函数被删除,并注意到编译器已经生成了B::B:

../test.cpp(155): error C2280: "B::B(void)" : Es wurde versucht, auf eine gelöschte Funktion zu verweisen
../test.cpp(152): note: Compiler hat hier "B::B" generiert

(对不起,我无法说服msvc和我说英语(

这两个代码更改中的任何一个都可以修复它:

struct A{
int i; //removed initialzation of member to 1
};

struct B{
B(){} //adding explicit default constructor
union{A a;};
};

我知道添加一个什么都不做的默认构造函数并不是一个复杂或令人讨厌的解决方法,但我真的想知道C++为什么强迫我这么做。

这是因为[class.default.cctor]p2说:

类X的默认构造函数被定义为已删除,如果:

  • (2.1(X是一个并集,它有一个带有非平凡默认构造函数的变体成员

。。。。。

我们可以看到为什么A没有一个来自[class.default.cctor]p3的琐碎默认构造函数,它说:

如果默认构造函数不是用户提供的,并且如果:
-(3.1(-其类没有虚拟函数(10.6.2(和虚拟基类(10.6.1(,并且
-(3.2(-其没有非静态数据成员类有一个默认的成员初始值设定项(10.3(,并且
-(3.3(-所有其类的直接基类具有琐碎的默认构造函数,和
-(3.4(-对于其类中的所有非静态数据成员对于类类型(或其数组(,每个此类都有一个平凡的默认构造函数。

我们可以从这个活的godbolt示例中看到删除非静态成员初始值设定项可以使程序格式良好。

struct A{
int i ; // no NSDMI
};
struct B{
union{A a;};
};

形成我们今天措辞的文件是2244:1无限制工会(修订版2(,它涵盖了这里的理性:

我们还更改了隐式声明特殊的方式工会的成员函数生成如下方法:如果为工会的任何成员,或类,则该特殊成员函数将被隐式删除(8.4¶10(。这会阻止编译器尝试编写它不知道如何编写的代码,并强制如果需要的话,程序员可以编写代码。事实上编译器不能编写这样的函数。没有理由不让程序员这样做。

一个联合只有一个活动成员,如果不能默认构造一个或多个成员,编译器应该如何选择默认激活哪个成员?