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

C++标准下,联合中非平凡类型数组仅初始化部分是否合法?

问题:C++联合内非平凡类型数组的部分元素初始化是否合法?

定义包含std::string数组的联合代码如下:

using namespace std;

struct MyUnion {
    union {
        char c;
        string s[5];
    };
    MyUnion() {}
    ~MyUnion() {}
};

随后通过placement new仅初始化数组的前2个元素并使用的代码:

MyUnion mu;

// 用placement new构造2个string
new (&mu.s[0]) string();
new (&mu.s[1]) string();

// 使用这两个string
do_something(mu.s[0]);
do_something(mu.s[1]);

// 析构这两个string
mu.s[0].~string();
mu.s[1].~string();

请问按照C++标准,这种仅初始化数组部分元素并使用的操作是否合法?(注:此问题曾被误标为重复,本问题聚焦数组的部分初始化场景,现有重复问题未覆盖该内容。)


回答

这种操作是合法的,依据C++标准的核心规则如下:

  1. 联合活跃成员的切换规则
    联合的活跃成员可通过显式构造新对象切换。当你用placement new构造mu.s[0]和mu.s[1]时,联合的活跃成员从默认的char c切换为数组s中被构造的元素对应的存储区域,这完全符合C++标准对联合成员激活的要求。

  2. 数组元素的独立生命周期管理
    数组的每个元素都是独立对象。对于非平凡类型数组,标准允许按需单独构造部分元素,只要确保:

    • 被构造的元素都被正确析构
    • 未构造的元素绝不被访问
      未构造的元素不存在合法生命周期,访问会触发未定义行为,但只使用已构造的元素完全合规。
  3. 非平凡类型在联合中的手动管理要求
    由于MyUnion的默认构造/析构函数无法自动处理std::string这类非平凡类型的生命周期,你通过placement new手动构造、显式调用析构函数的方式,完全契合C++标准的规定——这类场景下,程序员必须手动负责非平凡成员的构造与析构逻辑。

需要额外注意:

  • 绝对不能访问mu.s[2]到mu.s[4]这些未构造的元素
  • 必须保证每个被构造的std::string都被显式析构,避免内存泄漏

内容的提问来源于stack exchange,提问作者eyelash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:42:44