首页 > 解决方案 > 没有构造函数的 C++ 零初始化

问题描述

我不明白对于具有其成员默认值的结构的零初始化会发生什么。

如果我有这些结构:

struct A {
  int *a;
  int b;
};

struct B {
  int *a;
  int b;
  B() : b(3) {}
};

struct C {
  int *a;
  int b = 3;
};

我们可以毫无疑问地说:

现在还不清楚当我执行以下操作时会发生什么,以下是使用 gcc 的结果:

C c; // {garbage, 3}
C c{}; // {nullptr, 3}

问题是:如果我明确地构造对象,是否保证C c{}; 初始化C::anullptr,换句话说,默认成员C仍然为零会初始化其他成员C c{};吗?

因为如果我有一个与C(如 in B)执行相同操作的构造函数,则不会发生这种情况,因此其他成员不是零初始化的,但为什么呢?B和 和有什么不一样C

标签: c++structconstructorinitialization

解决方案


从 C++14 开始,C是一个聚合(如A),并且C c{}语法执行聚合初始化。这部分包括:

[dcl.init.aggr]/8如果列表中的初始化子句少于非联合聚合中的元素,则每个未显式初始化的元素按如下方式初始化:
(8.1) — 如果元素具有默认成员初始化程序(12.2),元素从该初始化程序初始化。
(8.2) — 否则,如果元素不是引用,则从空的初始化列表 (11.6.4) 复制初始化该元素。
(8.3) — 否则,程序格式错误。

所以C c{};等价于C c{{}, 3};。用空列表初始化int*成员会导致它被零初始化。

在 C++11 中,Cis 不是聚合(具有默认成员初始化程序被取消资格),并C c{};调用隐式定义的构造函数,使c.a成员未初始化。

在标准的所有版本中,B由于用户定义的构造函数,不是聚合。B b{};调用该构造函数,该构造函数显式初始化b成员并选择保持a未初始化状态。


推荐阅读