C++ 默认构造函数与具有非平凡默认构造函数的变体成员联合
C++ Default constructors in union with variant member with non-trivial default constructor
>我最近读了对联合默认构造函数的描述: 默认构造函数
有以下规则:
块引用 删除了隐式声明的默认构造函数: [...]T 是具有至少一个具有非平凡默认构造函数的变体成员的联合,并且 T 的任何变体成员都没有默认成员初始值设定项。[...]
然后我决定做一个练习并验证规则。
struct Member {
public:
// Member() : mX(0) {}
virtual int GetX() {
return mX;
}
int mX;
};
union DefaultConstructor {
int mA;
Member mMember;
int GetA();
};
使用 gcc v5.3.1(我知道它很旧(我收到预期的错误:
> ../src/DefaultConstrcutors.cpp: In function ‘void
> Test_DefaultConstructors()’: ../src/DefaultConstrcutors.cpp:26:22:
> error: use of deleted function
> ‘DefaultConstructor::DefaultConstructor()’ DefaultConstructor foo;
> ^ In file included from ../src/DefaultConstrcutors.cpp:19:0:
> ../src/DefaultConstructors.h:155:7: note:
> ‘DefaultConstructor::DefaultConstructor()’ is implicitly deleted
> because the default definition would be ill-formed: union
> DefaultConstructor {
> ^ ../src/DefaultConstructors.h:157:10: error: union member ‘DefaultConstructor::mMember’ with non-trivial ‘Member::Member()’
> Member mMember;
> ^
好的,所以根据规则,如果我为变体成员提供默认成员初始值设定项,那么它应该编译。所以我将联合定义更改为:
union DefaultConstructor {
int mA = 0;
Member mMember;
int GetA();
};
现在它应该编译,但我收到了同样的错误。
下一步是为 mMember 而不是 mA 提供默认初始值设定项(只有一个联合变体成员可能具有默认初始值设定项(。
union DefaultConstructor {
int mA;
Member mMember{};
int GetA();
};
现在它编译了。
问题是:当 mA 具有默认初始值设定项时,为什么它没有在第二种情况下编译?根据上述规则,这应该是可能的。这里还提供了更多类似的规则:工会声明
如果联合包含具有非平凡的非静态数据成员 默认构造函数,删除联合的默认构造函数 默认情况下,除非联合的变体成员具有默认成员 初始 化。
任何人都知道为什么它不起作用?
问候 皮奥特
cppReference通常是一个很好的信息源,但这里的编译器是正确的。C++11的n3337草案在9.5 Unions [class.union]中包含一个非规范但明确的注释,内容如下:
如果联合的任何非静态数据成员具有非平凡的默认值 构造函数 (12.1(, 复制构造函数 (12.8(, 移动构造函数 (12.8(, 复制赋值运算符 (12.8(, 移动 赋值运算符(12.8(,或析构函数(12.4(,联合的相应成员函数必须是 用户提供,否则将隐式删除 (8.4.3( 对于联合。
没有提到不会是一个成员具有默认成员初始值设定项的情况。
同样的注释仍然存在于C++4296草案的n14中,因此我认为它在实际的C++标准中应该仍然相同。注释当然是非规范性的,但它们的目的是更清楚地解释标准,所以我假设对cpp偏好的解释是错误的,因为它不尊重该注释,并且gcc解释是正确的。
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 初始化具有非默认构造函数的std::数组项的更好方法
- 具有默认模板类型的默认构造函数的类型推导
- 如何使用非默认构造函数实例化模板化类
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 声明没有默认构造函数的字段
- 没有默认构造函数作为模板参数的自定义比较器
- C++17 没有默认构造函数的地图放置(私有默认构造函数)
- 使用移动调用对等构造函数unique_ptr默认构造函数
- C++复制构造函数和默认构造函数
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 为什么即使我调用参数化构造函数也会调用默认构造函数?
- 具有非默认构造函数的单例类
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 如何处理没有默认构造函数但在另一个构造函数中构造的对象?
- 在C++中使用默认构造函数初始化对象的不同方法
- 在没有默认构造函数的情况下创建的派生对象
- 强制使用默认构造函数对成员进行未初始化的声明
- 使用默认构造函数初始化对象的不同方法
- 创建类类型的动态分配数组,其中类不得具有默认构造函数