C++嵌套聚合初始化:为何前两行代码编译失败?
先明确结构体的嵌套关系:A包含一个成员B b[2](长度为2的B数组),B包含一个成员int i[2](长度为2的int数组)。结合C++聚合初始化规则,逐个分析四条语句:
第一个语句:
A{{0, 0}, {0, 0}};A是聚合体,它只有一个成员b数组。根据规则,当给A的初始化列表传入初始化器列表(比如{0,0})作为第一个元素时,这个列表会被用来直接初始化b数组。但此时又传入了第二个{0,0},相当于给A仅有的一个成员提供了两个初始化器,超出了成员数量,因此触发“too many initializers for ‘A’”错误。第二个语句:
A{{0, 0}, B{0, 0}};
逻辑和第一个完全一致:第一个{0,0}被当作A的成员b数组的初始化器,第二个B{0,0}成了多余的初始化器,超出了A的成员初始化需求,因此报错。第三个语句:
A{B{0, 0}, {0, 0}};
第一个元素是B{0,0},这是一个具体的B类型对象,而非初始化器列表。此时C++会将它解释为b数组的第一个元素的初始化值;第二个{0,0}则被解释为b数组的第二个元素的初始化器(用来构造一个B对象)。整个初始化列表刚好匹配b数组的两个元素,编译合法。第四个语句:
A{B{0, 0}, B{0, 0}};
两个元素都是明确的B类型对象,分别初始化b数组的两个元素,完全符合聚合初始化规则,编译通过。
核心差异
当初始化器是{...}形式的初始化列表时,会优先被用来初始化聚合体的直接成员(即A的b数组);而当初始化器是具体的对象(比如B{0,0})时,会被当作数组成员的元素初始化器。这就是前两行报错、后两行正常的根本原因。
内容的提问来源于stack exchange,提问作者ZisIsNotZis

