Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ order of element initialization in aggregate class [duplicate]

Tags:

c++

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?

like image 991
Peeter Joot Avatar asked Feb 27 '12 15:02

Peeter Joot


4 Answers

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.

like image 111
Sebastian Mach Avatar answered Oct 01 '22 13:10

Sebastian Mach


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.

like image 30
Mike Seymour Avatar answered Oct 01 '22 13:10

Mike Seymour


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."

like image 36
ouah Avatar answered Oct 01 '22 12:10

ouah


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.

like image 45
Johannes Schaub - litb Avatar answered Oct 01 '22 11:10

Johannes Schaub - litb