为什么我的struct的成员没有使用`{}`正确初始化?

时间:2013-02-10 12:37:37

标签: c++ initialization c++-faq

我有以下代码:

#include <iostream>

struct T
{
   int a, b, c;
};

int main()
{
   T t = {0};
   std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}

Output

0,0,0

在关键生产环境中快速运行此代码多年后,服务于一个重要功能,项目的要求发生了变化,我需要输出为1,1,1

所以,我将{0}更改为{1}

#include <iostream>

struct T
{
   int a, b, c;
};

int main()
{
   T t = {1};
   std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}

Output

1,0,0

我期待1,1,1

为什么我的struct成员并非全部正确初始化?

1 个答案:

答案 0 :(得分:30)

当您编写= {0}时,只显式初始化第一个成员;其余的是根据标准隐式零初始化,所以乍一看你用你写的0显式初始化了所有成员,但是你没有

您编写0的地方仅影响第一个成员。所以当有一天,你把它改成1,认为它会改变所有成员时,你会有一个错误,就像这里一样。 这是误导/危险/愚蠢/脆弱的代码。

出于这个原因,如果没有附带的解释性评论,= {0}将无法通过我的团队中的代码审核。你本来应该写的:

T t = {};

现在,要根据新要求解决问题,您应该写:

T t = {1,1,1};

或者,如果您不介意struct可能失去POD,请给T一个构造函数。


正式措辞

  

[C++11: 8.5.1/2]:当聚合由初始化列表初始化时,如8.5.4中所述,初始化列表的元素被视为聚合成员的初始化者,增加下标或成员顺序。每个成员都从相应的 initializer-clause 进行复制初始化。如果 initializer-clause 是表达式,并且转换表达式需要缩小转换(8.5.4),则程序格式错误。 [..]

     

[C++11: 8.5.1/6]:如果 initializer-clauses 的数量超过要初始化的成员或元素的数量,则初始化列表格式不正确。

     

[C++11: 8.5.1/7]: 如果列表中的 initializer-clauses 少于聚合中的成员,那么未显式初始化的每个成员都应从空的初始化列表初始化(8.5.4)。