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

C风格数组成员初始化编译报错,为何与std::array表现不同?

C风格数组与std::array初始化行为差异问题

问题场景

初始化C风格数组成员时遇到编译错误,但将成员改为std::array即可正常编译,代码示例如下:

struct A {
  A(int aa) : a(aa) {}

  A(const A &a) = delete;
  A &operator=(const A &a) = delete;

private:
  int a;
  std::vector<int> v;
};

struct B1 {
  B1() : a1{{{1}, {2}}} {} // 编译通过(GCC 9.2)

private:
  std::array<A, 2> a1;
};

struct B2 {
  B2()
    : a2{{1}, {2}} // 编译错误:使用已删除的函数'A::A(const A&)'(GCC 9.2)
  {}

private:
  A a2[2];
};

疑问与额外观察

  • 为何C风格数组和std::array的编译器行为存在差异?原本以为二者功能基本一致(已知std::array更偏向聚合类型,而非vector那样的纯容器,可能理解有误)。
  • 额外观察:
    • 若移除A中的std::vector<int>成员,编译器允许初始化C风格数组;
    • GCC 9.5无此问题,这是否属于GCC Bug?

确认结论

经确认这是GCC的Bug,详情为:无拷贝构造函数时,数组的大括号初始化有时会失败(该Bug在GCC 4.9中被报告,于GCC 9.4中修复)。


问题解答

核心原因:GCC旧版本的编译实现Bug

在GCC 9.4之前的版本中,对C风格数组的聚合初始化存在实现缺陷:当数组元素类包含**非平凡成员(比如std::vector)**且禁用了拷贝构造函数时,编译器错误地尝试通过拷贝构造来完成数组元素的初始化,而非直接调用元素的构造函数。

而std::array作为标准库定义的聚合类型,其初始化逻辑在GCC中的实现更为规范,能够正确识别并直接调用元素的构造函数完成初始化,因此不会触发拷贝构造函数的错误。

当移除A中的std::vector成员后,类A变为平凡类型,GCC旧版本的数组初始化逻辑可以正常处理,因此编译通过。GCC 9.4及后续版本修复了这个C风格数组初始化的Bug,所以GCC 9.5中不再出现该问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:16:02