没有构造函数的 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;
};
我们可以毫无疑问地说的是:
A a;
保留所有字段未初始化
A a{};
是 {nullptr, 0}
B b;
和B b{};
都是{garbage, 3}(调用了构造函数)
现在不清楚当我执行以下操作时会发生什么,这里是使用 gcc 的结果:
C c; // {garbage, 3}
C c{}; // {nullptr, 3}
问题是:C c{};
是否保证 C::a
被初始化为 nullptr
,换句话说,是否有像这样的默认成员在 C
中,如果我像 C c{};
?
这样显式构造对象,仍然会零初始化其他成员
因为如果我有一个构造函数与 C
做同样的事情(比如 B
),那么其他成员是 而不是 零初始化,但为什么呢? B
和 C
有什么区别?
从 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{};
所有成员都默认初始化
我不明白对于其成员具有默认值的结构的零初始化会发生什么。
如果我有这些结构:
struct A {
int *a;
int b;
};
struct B {
int *a;
int b;
B() : b(3) {}
};
struct C {
int *a;
int b = 3;
};
我们可以毫无疑问地说的是:
A a;
保留所有字段未初始化A a{};
是 {nullptr, 0}B b;
和B b{};
都是{garbage, 3}(调用了构造函数)
现在不清楚当我执行以下操作时会发生什么,这里是使用 gcc 的结果:
C c; // {garbage, 3}
C c{}; // {nullptr, 3}
问题是:C c{};
是否保证 C::a
被初始化为 nullptr
,换句话说,是否有像这样的默认成员在 C
中,如果我像 C c{};
?
因为如果我有一个构造函数与 C
做同样的事情(比如 B
),那么其他成员是 而不是 零初始化,但为什么呢? B
和 C
有什么区别?
从 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{};
所有成员都默认初始化