为什么我的结构的成员没有使用`{}`正确初始化?
我有以下代码:
#include <iostream> struct T { int a, b, c; }; int main() { T t = {0}; std::cout << ta << ',' << tb << ',' << tc << '\n'; }
输出 :
0,0,0
经过多年的代码运行,在关键的生产环境中快乐地工作,发挥了至关重要的作用,项目的需求发生了变化,需要的输出是1,1,1
。
所以,我将{0}
更改为{1}
:
#include <iostream> struct T { int a, b, c; }; int main() { T t = {1}; std::cout << ta << ',' << tb << ',' << tc << '\n'; }
输出 :
1,0,0
我预计1,1,1
。
为什么我的struct
的成员没有被正确初始化?
当你写= {0}
时,只显式初始化第一个成员 ; 其余的都是按照标准隐含地初始化的,所以乍一看你明确地初始化了所有的成员,而你写的是0
, 但是你没有 。
你写0
地方只影响第一个成员。 所以有一天,当你把它改成1
以为它会改变所有的成员,你会有一个bug,就像这里。 这是误导/危险/愚蠢/脆弱的代码。
因此,如果没有相应的解释性评论, = {0}
不会在我的团队中通过代码审查。 你原本应该写:
T t = {};
而现在,要根据新的要求解决你的问题,你应该写:
T t = {1,1,1};
或者,如果你不介意你的struct
可能会失去POD性,给T
一个构造函数。
正式的措辞
[C++11: 8.5.1/2]:
按照8.5.4的规定,当初始化器列表初始化一个聚合器时,初始化器列表的元素将作为聚合器成员的初始化符,增加下标或会员订单。 每个成员都从相应的初始化子句复制初始化。 如果初始化子句是一个expression式,并且需要一个缩小的转换(8.5.4)来转换expression式,则该程序是格式不正确的。 [..]
[C++11: 8.5.1/6]:
如果初始化子句的数量超过要初始化的成员或元素的数量,则初始化子列表格式不正确。
[C++11: 8.5.1/7]:
如果列表中的初始化子句less于聚合中的成员,则未初始化的每个成员都应该从空初始化列表 (8.5.4) 初始化, 。