struct Foo
{
char name[10];
int i;
double d;
};
我知道我可以用以下内容对所有POD类型的所有成员进行零初始化:
Foo foo = {0};
我可以进一步简化为:
Foo foo = {};
与原生数组一样? (int arr[10] = {};
)
我不问在用{0}
进行初始化时,除了第一个成员之外的成员是否都是零初始化的。我知道这个问题的答案是肯定的。我问是否可以在语法上省略第一个0
。
我在这个主题上发现的大部分教程建议使用{0}
,没有使用{}
,例如this guide,并且它被解释为这是有效的,因为聚合初始化规则是递归; ,这比解释更容易引起混淆。
答案 0 :(得分:4)
如上所述,这是聚合初始化。适用的规则是(§8.5.1[dcl.init.aggr] / p7):
如果列表中的 initializer-clauses 少于 聚合中的成员,然后每个成员未明确初始化 应从其大括号或等于初始化程序或if,如果 来自空的初始化程序没有大括号或等于初始化程序 清单(8.5.4)。
§8.5.4[dcl.init.list] / p3的相关部分是:
定义了
T
类型的对象或引用的列表初始化 如下:
- 如果
T
是聚合,则执行聚合初始化(8.5.1)。- 否则,如果初始化列表没有元素,
T
是具有默认构造函数的类类型,则对象为 值初始化。- [无关项目省略]
- 否则,如果初始化列表没有元素,则对象将进行值初始化。
简而言之,子聚合是从空的初始化列表中递归聚合初始化的。其他一切都是价值初始化的。因此,最终结果是所有内容都是值初始化的,所有内容都是POD,值初始化意味着零初始化。
如果T
是POD但不是聚合,则聚合初始化不适用,因此您点击§8.5.4[dcl.init.list] / p3中的第二个项目符号点,这会产生值 - 而是整个对象的初始化。 POD类必须有一个简单的(因此不是用户提供的)默认构造函数,因此它们的值初始化意味着零初始化。