[dcl.init.aggr] (original) (raw)

9 Declarations [dcl.dcl]

9.4 Initializers [dcl.init]

9.4.1 Aggregates [dcl.init.aggr]

[ Note

:

Aggregate initialization does not allow accessing protected and private base class' members or constructors.

end note

]

The elements of an aggregate are:

When an aggregate is initialized by an initializer list as specified in [dcl.init.list], the elements of the initializer list are taken as initializers for the elements of the aggregate.

The explicitly initialized elementsof the aggregate are determined as follows:

For each explicitly initialized element:

For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:

If the aggregate is a union and the initializer list is empty, then

[ Example

:

struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" };

initializesss.awith 1,ss.bwith "asdf",ss.cwith the value of an expression of the formint{}(that is, 0), and ss.d with the value of ss.b[ss.a](that is, 's'), and in

struct X { int i, j, k = 42; }; X a[] = { 1, 2, 3, 4, 5, 6 }; X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };

a and b have the same value

struct A { string a; int b = 42; int c = -1; };

A{.c=21} has the following steps:

end example

]

The initializations of the elements of the aggregate are evaluated in the element order.

That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.

An aggregate that is a class can also be initialized with a single expression not enclosed in braces, as described in [dcl.init].

The destructor for each element of class type is potentially invoked ([class.dtor]) from the context where the aggregate initialization occurs.

[ Note

:

This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([except.ctor]).

end note

]

[ Example

:

int x[] = { 1, 3, 5 };

declares and initializesxas a one-dimensional array that has three elements since no size was specified and there are three initializers.

end example

]

An array of unknown bound shall not be initialized with an empty braced-init-list {}.91

[ Note

:

A default member initializer does not determine the bound for a member array of unknown bound.

Since the default member initializer is ignored if a suitable mem-initializer is present ([class.base.init]), the default member initializer is not considered to initialize the array of unknown bound.

[ Example

:

struct S { int y[] = { 0 }; // error: non-static data member of incomplete type };

end example

]

end note

]

[ Note

:

Static data members, non-static data members of anonymous union members, and unnamed bit-fields are not considered elements of the aggregate.

[ Example

:

struct A { int i; static int s; int j; int :17; int k; } a = { 1, 2, 3 };

Here, the second initializer 2 initializesa.jand not the static data memberA​::​s, and the third initializer 3 initializes a.kand not the unnamed bit-field before it.

end example

]

end note

]

[ Example

:

char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error

is ill-formed.

end example

]

If a member has a default member initializer and a potentially-evaluated subexpression thereof is an aggregate initialization that would use that default member initializer, the program is ill-formed.

[ Example

:

struct A; extern A a; struct A { const A& a1 { A{a,a} }; // OK const A& a2 { A{} }; // error }; A a{a,a}; // OK

struct B { int n = B{}.n; // error };

end example

]

If an aggregate class C contains a subaggregate elemente with no elements, the initializer-clause for e shall not be omitted from an initializer-list for an object of typeC unless the initializer-clauses for all elements of C following e are also omitted.

[ Example

:

struct S { } s; struct A { S s1; int i1; S s2; int i2; S s3; int i3; } a = { { }, // Required initialization 0, s, // Required initialization 0 }; // Initialization not required for A​::​s3 because A​::​i3 is also not initialized

end example

]

When initializing a multi-dimensional array, theinitializer-clausesinitialize the elements with the last (rightmost) index of the array varying the fastest ([dcl.array]).

[ Example

:

int x[2][2] = { 3, 1, 4, 2 };

initializesx[0][0]to3,x[0][1]to1,x[1][0]to4, andx[1][1]to2.

On the other hand,

float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } };

initializes the first column ofy(regarded as a two-dimensional array) and leaves the rest zero.

end example

]

If theinitializer-listbegins with a left brace, then the succeeding comma-separated list ofinitializer-clausesinitializes the elements of a subaggregate; it is erroneous for there to be moreinitializer-clausesthan elements.

If, however, theinitializer-listfor a subaggregate does not begin with a left brace, then only enoughinitializer-clausesfrom the list are taken to initialize the elements of the subaggregate; any remaininginitializer-clausesare left to initialize the next element of the aggregate of which the current subaggregate is an element.

[ Example

:

float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, };

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the arrayy[0], namelyy[0][0],y[0][1], andy[0][2].

Likewise the next two lines initializey[1]andy[2].

The initializer ends early and thereforey[3]s elements are initialized as if explicitly initialized with an expression of the formfloat(), that is, are initialized with0.0.

In the following example, braces in theinitializer-listare elided; however theinitializer-listhas the same effect as the completely-bracedinitializer-listof the above example,

float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 };

The initializer forybegins with a left brace, but the one fory[0]does not, therefore three elements from the list are used.

Likewise the next three are taken successively fory[1]andy[2].

end example

]

All implicit type conversions ([conv]) are considered when initializing the element with an assignment-expression.

Otherwise, if the element is itself a subaggregate, brace elision is assumed and theassignment-expressionis considered for the initialization of the first element of the subaggregate.

[ Note

:

As specified above, brace elision cannot apply to subaggregates with no elements; aninitializer-clause for the entire subobject is required.

end note

]

[ Example

:

struct A { int i; operator int(); }; struct B { A a1, a2; int z; }; A a; B b = { 4, a, a };

b.a1.iis initialized with 4,b.a2is initialized witha,b.zis initialized with whatevera.operator int()returns.

end example

]

[ Note

:

An aggregate array or an aggregate class may contain elements of a class type with a user-declared constructor ([class.ctor]).

Initialization of these aggregate objects is described in [class.expl.init].

end note

]

When a union is initialized with an initializer list, there shall not be more than one explicitly initialized element.

[ Example

:

union u { int a; const char* b; }; u a = { 1 }; u b = a; u c = 1; // error u d = { 0, "asdf" }; // error u e = { "asdf" }; // error u f = { .b = "asdf" }; u g = { .a = 1, .b = "asdf" }; // error

end example

]

[ Note

:

As described above, the braces around theinitializer-clausefor a union member can be omitted if the union is a member of another aggregate.

end note

]

The syntax provides for empty braced-init-lists, but nonetheless C++ does not have zero length arrays.