具有聚合初始化的这种代码是有效的 C++ 程序吗?
#include <iostream>
#include <numeric>
struct Sheet {
const int c[2]{};
const int sum = std::accumulate(std::begin(c), std::end(c), 0);
};
int main() {
Sheet sheet0;
Sheet sheet1{{10}};
Sheet sheet2{{10, 20}};
std::cout << sheet0.sum << "\n";
std::cout << sheet1.sum << "\n";
std::cout << sheet2.sum << "\n";
}
// Outputs:
// 0
// 10
// 30
这是一个具有类似 Excel 表行为的结构:用户使用一些值初始化单元格,如果用户不初始化,sum
则它会获取单元格值的计算总和。
我不确定在聚合初始化中跳过的成员处是否发生内联成员初始化而不是零初始化。
我预计声明
Sheet sheet2{{10, 20}};
相当于
Sheet sheet2{{10, 20}, {}};
并输出0,但我的程序运行表明它们导致不同的输出30和0。
对于
Sheet sheet2{{10, 20}};
,数据成员sum
将由其默认成员初始化程序初始化。它与初始化Sheet sheet2{{10, 20}, {}};
位置不同。sum
{}
具体来说,对于
Sheet sheet0;
,数据成员c
和sum
将由其默认成员初始化器初始化。 的 2 个元素c
将为零。对于
Sheet sheet1{{10}};
,c
将由 初始化{10}
,sum
将由其默认成员初始化器初始化。由于{10}
仅包含 1 个初始化器,小于 的成员数量为c
2,因此 的第一个元素c
将是10
,而第二个元素将是零。对于
Sheet sheet2{{10, 20}};
,c
将由 初始化{10, 20}
,sum
将由其默认成员初始化器初始化。结果 的第一个元素c
将是10
,而第二个元素将是20
。程序没有任何问题。行为定义明确,保证符合您所观察到的行为。
如果在聚合初始化中没有为聚合元素提供初始化程序,则除非
= {}
它具有默认成员初始化程序,否则它将c
被初始化为 。无论哪种方式,在聚合初始化中没有相应初始化程序的 元素都将因此被初始化为0
。sum
在类中声明得晚于c
,因此它的初始化顺序在 的初始化之后c
。由于给出了默认成员初始化程序,因此将使用该初始化程序来初始化它,并且由于排序,c
此时已经初始化并可用。