【发布时间】:2021-04-29 08:15:04
【问题描述】:
我不明白对于具有其成员默认值的结构的零初始化会发生什么。
如果我有这些结构:
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有什么区别?
【问题讨论】:
-
ot:我想我是迂腐的,但“垃圾”一词在这里完全用词不当。没有垃圾。它是一个不确定的值。如果不违反语言规则(未定义的行为),您将无法看到该值,如果您这样做,它可能会显示为垃圾,但它不是。
-
之所以提到它,是因为“垃圾神话”有时很难讨论此类实验的结果:事实上,您无法区分
3或nullptr和“垃圾”,因为如果您的代码具有未定义的行为,无法保证您得到错误/意外的输出 -
答案在 C++11 和 C++14 之间发生了变化。在 C++11 中,
C不是聚合,并且列表初始化调用了一个隐式定义的构造函数,该构造函数不会初始化a。在 C++14 中,C是一个聚合,并且列表初始化将所有未在 brace-init 列表中或由成员声明中指定的初始化程序赋予值的成员初始化为零.由于用户定义的构造函数,B不是聚合方式。 -
相关文章:the fickle aggregate.
标签: c++ struct constructor initialization