数组初始化,引用前一个元素是否可行?

11
const QPointF points[] =
{
    QPointF(r.left() - i, r.top() - i),
    QPointF(r.right() + i, r.top() - i),
    QPointF(r.right() + i, r.bottom() + i),
    QPointF(r.left() - i, r.bottom() + i),
    points[0] // is this line valid (according to the C++ standard)?
};

虽然这段代码可以通过MS Visual Studio编译器的编译,但我不确定它是否符合C++标准。

如果能提供标准中相关的引用,将十分感激


g++ -pedantic 没有抱怨。 - kennytm
1
尽管它对于“const int x =x;”也没有抱怨。 - kennytm
我认为这是正确的(此时points[0]指向一个有效的对象),但我不能确定。语法检查通过,翻阅Stroustroup的书籍只是说“数组可以通过值列表进行初始化。points[0]是一个值,因此似乎是正确的。” - rtpg
@Dasuraga:不,points[0]在那个时候 并没有 指向一个有效的对象。points[0]有一个 不确定 的值。 - Lightness Races in Orbit
4个回答

4

C++03/C++11 答案


不,它不是。

在等号右侧,points确实存在1,但初始化器仅在其所有操作数被评估之后应用。

  • 如果points处于命名空间范围(因此具有静态存储期并已进行零初始化2),那么这是“安全的”,但你在那里使用points [0]会给你0,而不是QPointF(r.left() - i, r.top() - i)

  • 如果points具有自动存储期-它尚未初始化,因此您使用points[0]正在尝试使用未初始化的变量,其中points[0]具有不确定的值...这很糟糕3

难以为此提供标准参考资料,除了说明8.5“Initializers”中没有明确使此可能的规则,其他规则填补了剩余部分。


1 [n3290: 3.3.2/1]: The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example:

int x = 12;
{ int x = x; }

Here the second x is initialized with its own (indeterminate) value. —end example ]

2 [n3290: 3.6.2/2]: Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. [..]

3 [n3290: 17.6.3.3/2]: [..] [ Note: Operations involving indeterminate values may cause undefined behavior. —end note ]


我没有意识到这是一个有效的替代拼写 :) - EvilTeach
@EvilTeach:“Initialiser”是正确的英语拼写。带有“z”的“替代”拼写法出现在所谓的“美式英语”的一个变种中。我相信北美洲某些地方有一些人坚持使用这种改编后的词汇表。 - Lightness Races in Orbit

2

来自http://www.comeaucomputing.com/pcgi-bin/compiler.cgi

Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 8: warning: variable "points" is used before its value is set
      points[0] // is this line valid (according to the C++ standard)?

0

由于该语句中没有顺序点,结果是未定义的,就像在那个维基百科页面引用的i=i++示例一样。

换句话说,没有什么说明编译器应该先评估所有内容,然后分配,还是以何种顺序独立地评估分配每个元素。


嗯,我不知道为什么我没有想到那个。可能有一种更简单的方法来描述这种情况。 - Lightness Races in Orbit
至少规定了对每个元素的初始化程序求值的顺序。 - smerlin
@smerlin:你为什么这样认为?在 {.., ..} 中的逗号在这个上下文中不是“逗号运算符”。(类似于维基百科文章所引用的第4点:“请注意,函数调用 f(a,b,c) 不是逗号运算符的使用,a、b 和 c 的求值顺序是未指定的。”) - eudoxos
1
@eudoxos:虽然我答案中引用的标准并没有覆盖到OP的问题,但它涵盖了这个问题——而且它说顺序是指定的。 - smerlin

-2

旧答案(没有理解重点):

我查看了当前的C++0x草案,在那里我找到了句子8.5.1.17,它说:

17 在 初始化子句 中,完整表达式按照它们出现的顺序进行评估。

所以虽然这个句子不是2003年C++标准的一部分,但我相当确定如果这是C++0x的一部分,它应该在任何最新的编译器中都可以工作。

编辑:
评论让我重新考虑了这个问题。这行代码只确保QPointF对象按照数组初始化中它们出现的顺序创建(如果元素构造函数具有可观察的副作用,则相关)。问题是,在数组初始化期间,points的值是不确定的。因此,至少不能依赖于标准来保证points[0]的有效值。


2
我一点也看不出这与问题有任何关系。 - Lightness Races in Orbit
2
正确的,尽管评估必须在赋值之前进行,但它并没有说明何时分配值,这才是重要的。 - eudoxos
@eudoxos: 是的,你说得对,尽管只有一个值被分配。 - smerlin
@Tomalak Geret'kal:谢谢你的提示,我只考虑了数组初始化子句中的初始化顺序 :/ - smerlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接