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

GCC版本差异下数组成员变量移动构造编译异常问题咨询

GCC版本差异导致的移动构造函数编译错误分析

问题现象

  • 在GCC++ <= 9.3版本中,编译以下代码会触发已删除的移动构造函数被调用的错误,具体报错信息:
: In constructor 'Widget::Widget()': :16:24: error: use of deleted function 'Child::Child(Child&&)' 16 | Widget() : m_array{} {} | ^ :11:5: note: declared here 11 | Child(Child&&) = delete; | ^~~~~
  • 在GCC++ > 9.3版本中,该编译错误不再出现;另外,若注释掉基类Base的虚析构函数,旧版本GCC的错误也会消失。

核心疑问

这是编译器特定问题还是代码本身存在问题?

相关代码

class Base {
public:
    Base() {}
    virtual ~Base() = default;//注释掉此行后错误不再出现
    Base(Base&&) = delete;
};

class Child  : public Base{
public:
    Child() = default;
    Child(Child&&) = delete;
};

class Widget {
public:
    Widget() : m_array{} {}
private:
    Child m_array[2];
};

int main()
{
    Widget wd{};
}

问题分析与结论

这是GCC 9.3及更早版本的编译器bug,代码本身完全符合C++标准,不存在问题。

具体原因

  1. C++标准规定:Widget构造函数中m_array{}属于数组的值初始化,对于数组里的每个Child对象,应该调用其默认构造函数完成初始化——Child显式默认了默认构造函数,且Base的默认构造函数可用,完全满足初始化条件。
  2. 旧版GCC的错误逻辑:当基类Base存在虚析构函数时,GCC 9.3及更早版本错误地尝试调用Child已删除的移动构造函数来初始化数组元素,违背了标准规则。
  3. 错误消失的两种场景:
    • GCC 10及以上版本修复了这个bug,会正确调用默认构造函数;
    • 注释掉Base的虚析构函数后,旧版GCC的错误触发条件消失,因此不再报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:17:28