没有构造函数的 C++ 零初始化

C++ zero initialization without constructor

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

如果我有这些结构:

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::a 被初始化为 nullptr,换句话说,是否有像这样的默认成员在 C 中,如果我像 C c{};?

这样显式构造对象,仍然会零初始化其他成员

因为如果我有一个构造函数与 C 做同样的事情(比如 B),那么其他成员是 而不是 零初始化,但为什么呢? BC 有什么区别?

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

[dcl.init.aggr]/8 If there are fewer initializer-clauses in the list than there are elements in a non-union aggregate, then each element not explicitly initialized is initialized as follows:
(8.1) — If the element has a default member initializer (12.2), the element is initialized from that initializer.
(8.2) — Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list (11.6.4).
(8.3) — Otherwise, the program is ill-formed.

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

在 C++11 中,C 不是聚合(具有默认成员初始值设定项是不合格的),并且 C c{}; 调用隐式定义的构造函数,留下 c.a 成员未初始化。

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

Aggregate initialization - cppreference.com

  • If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized. If a member of a reference type is one of these remaining members, the program is ill-formed.

(until C++11)

  • If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) copy-initialized from empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.

(since C++11)

所以A a{};所有成员都默认初始化