C++11中如何初始化包含const成员的union?
C++11中带const成员的union初始化问题解决方案分析
问题背景
在C11中初始化包含const成员的union时,无法使用C20引入的指定初始化器(如.dbl = 42.1),默认聚合初始化只会初始化union的第一个成员;而const成员只能通过初始化或显式构造设置值,直接赋值操作是不允许的。
你提供的placement new方案的问题
你给出的代码存在未定义行为,原因如下:
my_union foo{};是值初始化,会激活union的第一个成员ptr(将其初始化为nullptr),此时ptr处于活跃状态。- 后续
new(&foo) double {42.1};是在union的存储空间上直接构造double对象,但这与union成员的类型不匹配(union的成员是const double,而非double),且未按标准流程终止原有活跃成员ptr的生命周期。 - 访问
foo.dbl时,dbl成员并未被正确激活——union的成员只有被显式初始化或构造后才会成为活跃成员,直接构造外部类型的对象无法激活union的目标成员,因此访问行为未定义。
合规的C++11解决方案
我们可以通过默认初始化union(不激活任何成员),再显式构造目标const成员的方式实现,代码如下:
#include <iostream> #include <new> union my_union { const void* ptr; const double dbl; }; int main() { // 默认初始化union,不激活任何成员 my_union foo; // 显式激活并构造const double类型的dbl成员 new(&foo.dbl) const double(42.1); std::cout << foo.dbl; }
该方案的合规性说明:
my_union foo;是默认初始化,对于无用户自定义构造函数的union聚合类型,默认初始化不会初始化任何成员,也不会激活任何成员,此时foo的存储空间处于未初始化状态。new(&foo.dbl) const double(42.1);通过placement new在union的dbl成员地址上构造const double对象,这会显式激活dbl作为union的活跃成员,后续访问foo.dbl完全符合标准,行为定义良好。
补充说明
由于union的成员都是平凡可析构类型(指针和double),无需手动调用析构函数,union对象生命周期结束时会自动释放存储空间。
内容的提问来源于stack exchange,提问作者François Andrieux
相关产品推荐
相关产品推荐

