为什么我的结构成员没有使用“{}”正确初始化?[复制]

Why are my struct's members not properly initialised using `{}`? [duplicate]

提问人:Lightness Races in Orbit 提问时间:2/10/2013 最后编辑:Matthieu M.Lightness Races in Orbit 更新时间:2/10/2013 访问量:5562

问:

我有以下代码:

#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

C 初始化 C++-FAQ

评论

0赞 Alok Save 2/10/2013
@Matthieu:为什么选择C++-faq标签?
2赞 Alok Save 2/10/2013
不是投反对票的人,但似乎人们不喜欢你的问题,这不是投反对票的充分理由,但人们在 SO 中猖獗地这样做。此外,对一个问题投反对票不会花费您任何代表,因此它是每个人都想享受的免费赠品。请注意,只有 Q 被否决,而不是答案(反对答案成本代表)。我在这里唯一的问题是为什么它被标记为 c++-faq?这是 SO 中的常见问题吗?难道没有现有的答案来解释这一点,就有资格成为常见问题解答吗?我在 Q 中没有看到任何不好的地方,我看不出它是常见问题解答的原因。
3赞 Lightness Races in Orbit 2/10/2013
我认为人们仍然不明白,尽管问题发布页面上有一个“回答这个问题”框,但鼓励自己写问题和答案。头脑真的令人难以置信。我只是在周末免费写一个深入的问答来帮助其他人。
2赞 Matthieu M. 2/10/2013
@AlokSave:我已经看过几次推荐的初始化,它确实带有一些奇怪的语义。我认为这样标记会很有帮助。{0}
0赞 Alok Save 2/10/2013
@MatthieuM.:我同意这是一个奇怪而重要的语义,但我相信遵循的常见做法/程序是找到现有的准确答案并将它们标记为常见问题解答,而不是创建新的常见问题解答条目。标记的副本(可能还有许多其他副本)不是已经准确详细地解释了这一点吗?为什么这有资格成为常见问题解答而不是其他许多常见问题解答?

答:

32赞 Lightness Races in Orbit 2/10/2013 #1

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

你写的那个地方只影响第一个成员。因此,当有一天,你把它改成认为它会改变所有成员时,你就会遇到一个错误,就像这里一样。这是误导性/危险/愚蠢/脆弱的代码。01

出于这个原因,如果没有附带的解释性评论,将不会在我的团队中通过代码审查。你最初应该写:= {0}

T t = {};

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

T t = {1,1,1};

或者,如果你不介意你可能会失去 POD,请给出一个构造函数。structT


正式措辞

[C++11: 8.5.1/2]:当聚合由初始值设定项列表初始化时(如 8.5.4 中指定),初始值设定项列表的元素将作为聚合成员的初始值设定项,按递增的下标或成员顺序排列。每个成员都从相应的初始值设定项子句进行复制初始化。如果 initializer-clause 是一个表达式,并且需要缩小转换 (8.5.4) 来转换表达式,则程序格式不正确。[..]

[C++11: 8.5.1/6]:如果初始值设定项子句的数量超过要初始化的成员或元素的数量,则初始值设定项列表的格式不正确。

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

评论

12赞 Jonathan Leffler 2/10/2013
在 C(与 C++ 相反)中,表示法是将所有字段初始化为零的古老传统。某些版本的 GCC 在给定适当的选项(例如 4.1.x 到 4.6.x)时会警告“未完全初始化的结构”;较新的版本(例如 GCC 4.7.1)识别为特殊情况,并且在使用该表示法时不会生成警告。使用缩写表示法的一个原因是避免在结构更改时更改初始值设定项。(我不打算谈论这如何应用于 C++。= { 0 }= { 0 }
0赞 David G 3/22/2013
那么,我如何设法使它们全部初始化为 1 而不循环呢?
0赞 Lightness Races in Orbit 3/22/2013
@David:不能。无论如何,你不能绕过它们。