14

我有以下代码:

#include <iostream>

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

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

输出

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';
}

输出

1,0,0

1,1,1相反,我期待。

为什么我struct的成员没有被正确初始化?

4

1 回答 1

32

当您编写= {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]:如果初始化器子句的数量超过要初始化的成员或元素的数量,则初始化器列表是格式错误的。

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

于 2013-02-10T12:37:36.607 回答