c ++数组初始化

qba*_*qba 16 c++ arrays initialization

可能重复:
如何在C
数组初始化中初始化数组,引用前一个元素ok?

我想知道在c/c ++标准中进行这样的初始化是否安全:

int a = 5;
int tab[] = { a , tab[0] + 1 , tab[1] };
Run Code Online (Sandbox Code Playgroud)

它成功编译并执行gcc 4.5和clang 2.9,但它总是真的吗?


打印此表给出5 6 6.它在全球范围内初始化.


通常它在c和c ++中都很有趣,但我想在c ++中使用它:)

Lig*_*ica 7

C++ 03/C++ 11答案


不,它不会.

在右侧=,tab存在1但是 - 如果它具有自动存储持续时间 - 它尚未初始化,因此您使用tab[0]tab[1]使用未初始化的变量.

如果tab是在命名空间作用域(因此具有静态存储持续时间并且已经零初始化),那么这是"安全的",但是你的使用tab[0]不会给你5.

很难为此提供标准参考,除了说没有任何8.5 "Initializers"内容明确地使这成为可能,其他地方的规则填补其余部分.


1 [n3290: 3.3.2/1]:名称的声明点紧接在其完整的声明者(第8条)之后和其初始化者之前(如果有的话)[...]

  • @qba:再次阅读我的回答.你不能保证这个结果. (2认同)

Naw*_*waz 5

int a =5;
int tab[] = { a , tab[0] + 1 , tab[1] };
Run Code Online (Sandbox Code Playgroud)

如果这些变量是在命名空间范围内声明的,那么它们就可以了,因为在命名空间范围内变量是零初始化的(因为静态初始化 - 请详细阅读此内容).

但是如果它们在函数作用域声明,则第二行调用未定义的行为,因为局部变量不是静态初始化的,这意味着tab[0]并且tab[1]未初始化,用于初始化数组.读取未初始化的变量会调用未定义的行为.


Dav*_*eas 4

在C99标准中,似乎保证了成员初始化的顺序:

\n\n
\n

\xc2\xa76.7.8/17:每个大括号括起来的初始值设定项列表都有一个关联的当前对象。当没有指定时,当前对象的子对象将根据当前对象的类型按顺序初始化:数组元素按下标递增顺序,结构成员按声明顺序,以及联合的第一个指定成员。相反,指定会导致后面的初始化程序开始初始化指定符所描述的子对象。然后初始化继续按顺序向前进行,从指示符描述的下一个子对象开始。

\n
\n\n

但正如 @Tomalak 在评论中提到的那样,这并不能为操作提供完整的保证,因为编译器将首先评估所有参数,然后按之前的顺序应用结果。也就是说,前面的引用不会在 的初始化和用于初始化tab[0]的表达式的求值之间强加顺序(它仅在和 的初始化之间强加顺序)tab[0]+1tab[1]tab[0]tab[1]

\n\n

对于 C++ 标准,无论是当前标准还是即将推出的 C++0x 标准的 FDIS 似乎都没有特定的子句来定义初始化执行的顺序。唯一提到的订购来自

\n\n
\n

\xc2\xa78.5.1/2 当聚合被初始化时,初始值设定项可以包含一个初始值设定项子句,该初始值设定项子句由大括号括起来、以逗号分隔的聚合成员的初始值设定项子句列表组成,以递增的下标或成员顺序编写

\n
\n\n

但这仅与初始化程序中条目的写入顺序有关与实际评估方式无关。

\n