可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I was wondering about an initialization of the following form:
int array[] = { v - 1, array[0] + 1 } ;
In the initialization of the second element, the value of the first is used, but the entire array is not yet initialized. This happens to compile with g++, but I was unsure whether this is actually portable and a well defined construct?
回答1:
See 3.3.2 Point of declaration:
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 ]
So you are referring to the array correctly, its name is known after the =
.
Then, 8.5.1 Aggregates:
An aggregate is an array or a class [...]
17: The full-expressions in an initializer-clause are evaluated in the order in which they appear.
However, I see no reference to when the evaluated values are actually written into the array, so I wouldn't rely on this and would even go so far to declare your code as not well defined.
回答2:
As far as I can see, this is not well defined. The standard (C++11, 8.5.1/17) specifies that "The full-expressions in an initializer-clause are evaluated in the order in which they appear", but I can't see anything that requires each aggregate element to be initialised from the result of its initializer-clause before the next is evaluated.
回答3:
Can a (C/C++) array initialization reference itself?
This is also valid C code.
C has some correspondent paragraph (emphasis mine).
(C99, 6.2.1p7) "Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag. Each enumeration constant has scope that begins just after the appearance of its defining enumerator in an enumerator list. Any other identifier has scope that begins just after the completion of its declarator."
回答4:
I think this is handled by http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1343 . Initially my report was only about non-class initializers for namespace scope objects (see When exactly is an initializer temporary destroyed?), but the problem exists for aggregate elements just aswell if they are non-class. And as the additional recent note explains, even seems to exist for the entire aggregate initialization aswell, even if it is a class object, because then no constructor call happens that would enlargen the full-expression of the initializer.
If instead of int
you would have used a class, and the initialization would be a constructor call, then that constructor call would be part of the same full expression that encloses the aggregate-ininitializer element, so that here the order would be OK and your code would be well-defined.