c++ - C++ 默认构造函数与具有非平凡默认构造函数的变体成员联合
问题描述
我最近阅读了关于联合默认构造函数的描述: 默认构造函数
有以下规则:
Blockquote 已删除隐式声明的默认构造函数:[...] 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++14 的草案 n4296 中,所以我认为它在实际的 C++ 标准中应该仍然相同。注释当然是非规范的,但它们的目的是更清楚地解释标准,所以我认为 cppreference 的解释是错误的,因为它不尊重该注释,而 gcc 的解释是正确的。
推荐阅读
- python - django 按来自不同字段的最新日期对查询集进行排序
- php - 多数据搜索功能
- rally - Rally - 错误 - hydraModel 不是函数?
- ios - UINavigationController 改变 InteractivePopGesture 方向
- jenkins - groovy .execute waitFor 在 Jenkins 中挂起,但不是 CL
- python - datetime.now() 没有设置当前日期
- javascript - ejs中的if语句
- spring-boot - 从 Spring 升级到 Spring Boot 破坏了 JAX-WS 客户端配置
- java - 向警报对话框添加正确答案
- php - Cake php重定向错误[无法修改标头信息]