You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++11中如何初始化包含const成员的union?

C++11中带const成员的union初始化问题解决方案分析

问题背景

在C11中初始化包含const成员的union时,无法使用C20引入的指定初始化器(如.dbl = 42.1),默认聚合初始化只会初始化union的第一个成员;而const成员只能通过初始化或显式构造设置值,直接赋值操作是不允许的。

你提供的placement new方案的问题

你给出的代码存在未定义行为,原因如下:

  1. my_union foo{};是值初始化,会激活union的第一个成员ptr(将其初始化为nullptr),此时ptr处于活跃状态。
  2. 后续new(&foo) double {42.1};是在union的存储空间上直接构造double对象,但这与union成员的类型不匹配(union的成员是const double,而非double),且未按标准流程终止原有活跃成员ptr的生命周期。
  3. 访问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:57:31