c++ - 为什么一个结构有另一个结构作为成员包装在一个 union 中,如果没有显式默认构造函数则不能编译?

标签 c++ constructor language-lawyer unions default-constructor

这就是我所说的关系:

struct A{
    int i = 1;
};

struct B{
    union{A a;};
};

void main(){
    B b;
};

在这种情况下,我的编译器 (vs2015) 提示 B B::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.ctor]p2其中说:

A defaulted default constructor for class X is defined as deleted if:

  • (2.1) X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,

.....

我们可以看到为什么 A 没有来自 [class.default.ctor]p3 的普通默认构造函数其中说:

A default constructor is trivial if it is not user-provided and if:
- (3.1) — its class has no virtual functions (10.6.2) and no virtual base classes (10.6.1), and
- (3.2) —no non-static data member of its class has a default member initializer (10.3), and
- (3.3) — all the direct base classes of its class have trivial default constructors, and
- (3.4) — for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.

this live godbolt example可以看出 删除非静态成员初始值设定项会使程序结构良好。

struct A{
    int i ; // no NSDMI
};

struct B{
    union{A a;};
};

导致我们今天的措辞的论文是 n2544:1 Unrestricted Unions (Revision 2) ,它涵盖了这里的理性:

We have also changed the way implicitly declared special member functions of unions are generated in the following way: if a non-trivial special member function is defined for any member of a union, or a member of an anonymous union inside a class, that special member function will be implicitly deleted (8.4 ¶10) for t he union or class. This prevents the compiler from trying to write code that it cannot know how t o write, and forces the programmer to write that code if it’s needed. The fact that the compiler can’t write such a function is no reason not to let the programmer do so.

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

关于c++ - 为什么一个结构有另一个结构作为成员包装在一个 union 中,如果没有显式默认构造函数则不能编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53143245/

相关文章:

c++ - 变量在 C++ 中如何以及在哪里可能没有关联的名称?

c++ - 友元声明和显式模板实例化声明

c++ - 如何为 Android 编译我自己的 C++ 库?

java - 使用可变参数在 kotlin 中调用构造函数

c++ - 为什么无法通过将数据传递给某个函数来在全局范围内初始化数据?

c++ - 使用参数初始化另一个类构造函数中的对象

c++ - 什么时候允许推导 initializer_list?

c++ - (C++) 将指针传递到模板中

c++ - 如何在跳棋游戏中移动棋子

c++ - Eclipse 拼写引擎不存在