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

C++17中用{}初始化带deleted默认构造的结构体时float成员是否保证零初始化

C++17空大括号初始化删除默认构造的结构体成员零初始化判定
struct A {
  int x{};
};

struct S
{
  S() = delete;
 
  A a;
  float b;
};

int main()
{
  auto s = S{}; // Is s.b guaranteed to be zero?
}

在C++17标准下,s.b保证被零初始化,你看到的两段规则描述不存在本质矛盾,具体逻辑如下:

  1. 首先明确C17的聚合判定规则:C17要求聚合类型无用户提供的构造函数,在类定义中直接将默认构造声明为=delete不属于“用户提供”的范畴,因此S是合法的聚合类型。
  2. 空大括号初始化的顶层规则:当初始化对象是聚合类型时,优先执行聚合初始化,而非整体的值初始化,这就是你看到的第二段描述的规则,该规则的作用是判定初始化的总分支,不涉及后续成员的初始化逻辑。
  3. 聚合初始化的内部规则:当初始化列表为空时,未显式指定初始化器的成员,优先使用类内默认成员初始化器,没有类内初始化器的成员执行值初始化:
    • 成员a是A类型,没有类内初始化器,执行值初始化,调用A的隐式默认构造函数,其内部成员x有类内初始化器{},因此a.x被初始化为0;
    • 成员b是float标量类型,没有类内初始化器,执行值初始化,标量类型的值初始化规则就是零初始化,因此s.b的值保证为0。

你误以为的矛盾点本质是规则适用的阶段不同:第二段描述的是顶层初始化类型的选择逻辑,第一段描述的是聚合初始化内部的成员初始化逻辑,聚合初始化过程中对未显式初始化的成员单独执行值初始化,和针对整个类的整体值初始化是完全独立的两个规则,不存在冲突。

你看到的“存在删除的默认构造函数就不执行零初始化”的规则,仅适用于整体值初始化的场景,也就是被初始化的类型不是聚合、需要调用构造函数的情况,本场景下S是聚合,初始化全程不会调用S的构造函数,因此该规则不适用。

补充说明

  • C20修改了聚合判定规则:只要类存在用户声明的构造函数,无论是否是=delete/=default,都不再属于聚合类型,因此这段代码在C20及以后的标准下会直接编译报错,因为S{}会触发值初始化,尝试调用被删除的默认构造函数。
  • 目前所有主流编译器对C++17规则的实现都符合标准要求,确实会将s.b初始化为0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:24:02