含非平凡默认构造变体成员的Union默认构造函数疑问
关于Union默认构造函数的疑惑解答
嘿,这个问题其实藏着C++ union默认构造函数规则里一个容易忽略的细节,我来帮你梳理清楚~
首先回顾你的测试场景:
- 你定义了带虚函数的
Member类(拥有非平凡默认构造函数,因为虚函数会让构造函数变成非平凡) - 初始的
union DefaultConstructor包含int mA和Member mMember,实例化时报错——这符合规则:当union包含至少一个非平凡默认构造的成员,且没有任何成员带默认初始化器时,隐式默认构造函数会被删除。
接下来的测试结果让你疑惑:
- 给
mA加默认初始化器int mA = 0;,仍然编译报错; - 给
mMember加默认初始化器Member mMember{};,编译通过。
问题的核心:你看到的是简化版规则,完整规则还有额外条件
cppreference里关于union默认构造函数的完整规则是这样的:
若union包含至少一个带非平凡默认构造函数的变体成员,其隐式声明的默认构造函数会被删除,除非恰好有一个变体成员拥有默认成员初始化器,并且所有其他变体成员都是平凡默认构造的、非引用类型(C11起)、非const限定类型(C14起)。
这就是关键!当你给mA(平凡构造的int)加默认初始化器时,另一个成员mMember是非平凡默认构造的,不满足“所有其他成员都是平凡默认构造”的条件,所以union的隐式默认构造函数仍然会被删除,导致实例化报错。
而当你给mMember(非平凡构造的成员)加默认初始化器时,另一个成员mA是平凡默认构造的int,完全满足所有额外条件——此时union的隐式默认构造函数会被定义,它的行为就是初始化mMember这个带默认初始化器的成员,所以编译通过。
再换个场景验证一下
如果你的union里有两个平凡构造的成员,比如int mA和double mB,给其中一个加默认初始化器,union的默认构造函数会正常生成,因为其他成员都是平凡构造的,符合规则。
内容的提问来源于stack exchange,提问作者Piotr
相关产品推荐
相关产品推荐

