[dcl.init.aggr] # 9 Declarations [[dcl]](./#dcl) ## 9.5 Initializers [[dcl.init]](dcl.init#aggr) ### 9.5.2 Aggregates [dcl.init.aggr] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5475) An [*aggregate*](#def:aggregate "9.5.2 Aggregates [dcl.init.aggr]") is an array or a class ([[class]](class "11 Classes")) with - [(1.1)](#1.1) no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5 Constructors")), - [(1.2)](#1.2) no private or protected direct non-static data members ([[class.access]](class.access "11.8 Member access control")), - [(1.3)](#1.3) no private or protected direct base classes ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")), and - [(1.4)](#1.4) no virtual functions ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) or virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple base classes"))[.](#1.sentence-1) [*Note [1](#note-1)*: Aggregate initialization does not allow accessing protected and private base class' members or constructors[.](#1.sentence-2) — *end note*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5492) The [*elements*](#def:aggregate,elements "9.5.2 Aggregates [dcl.init.aggr]") of an aggregate are: - [(2.1)](#2.1) for an array, the array elements in increasing subscript order, or - [(2.2)](#2.2) for a class, the direct base classes in declaration order, followed by the direct non-static data members ([[class.mem]](class.mem "11.4 Class members")) that are not members of an anonymous union, in declaration order[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5503) When an aggregate is initialized by an initializer list as specified in [[dcl.init.list]](dcl.init.list "9.5.5 List-initialization"), the elements of the initializer list are taken as initializers for the elements of the aggregate[.](#3.sentence-1) The [*explicitly initialized elements*](#def:explicitly_initialized_elements,aggregate "9.5.2 Aggregates [dcl.init.aggr]") of the aggregate are determined as follows: - [(3.1)](#3.1) If the initializer list is a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"), the aggregate shall be of class type, the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in each [*designator*](dcl.init.general#nt:designator "9.5.1 General [dcl.init.general]") shall name a direct non-static data member of the class, and the explicitly initialized elements of the aggregate are the elements that are, or contain, those members[.](#3.1.sentence-1) - [(3.2)](#3.2) If the initializer list is a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]"), the explicitly initialized elements of the aggregate are those for which an element of the initializer list appertains to the aggregate element or to a subobject thereof (see below)[.](#3.2.sentence-1) - [(3.3)](#3.3) Otherwise, the initializer list must be {}, and there are no explicitly initialized elements[.](#3.3.sentence-1) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5529) For each explicitly initialized element: - [(4.1)](#4.1) If the element is an anonymous union member and the initializer list is a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"), the element is initialized by the[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") { *D* }, where *D* is the [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") naming a member of the anonymous union member[.](#4.1.sentence-1) There shall be only one such [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#4.1.sentence-2) [*Example [1](#example-1)*: struct C {union {int a; const char* p; }; int x;} c = { .a = 1, .x = 3 }; initializes c.a with 1 and c.x with 3[.](#4.1.sentence-3) — *end example*] - [(4.2)](#4.2) Otherwise, if the initializer list is a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"), the element is initialized with the [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") of the corresponding [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#4.2.sentence-1) If that initializer is of the form= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and a narrowing conversion ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")) is required to convert the expression, the program is ill-formed[.](#4.2.sentence-2) [*Note [2](#note-2)*: The form of the initializer determines whether copy-initialization or direct-initialization is performed[.](#4.2.sentence-3) — *end note*] - [(4.3)](#4.3) Otherwise, the initializer list is a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]")[.](#4.3.sentence-1) If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") appertains to the aggregate element, then the aggregate element is copy-initialized from the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#4.3.sentence-2) Otherwise, the aggregate element is copy-initialized from a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") consisting of all of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* that appertain to subobjects of the aggregate element, in the order of appearance[.](#4.3.sentence-3) [*Note [3](#note-3)*: If an initializer is itself an initializer list, the element is list-initialized, which will result in a recursive application of the rules in this subclause if the element is an aggregate[.](#4.3.sentence-4) — *end note*] [*Example [2](#example-2)*: struct A {int x; struct B {int i; int j; } b;} a = { 1, { 2, 3 } }; initializesa.x with 1,a.b.i with 2,a.b.j with 3[.](#4.3.sentence-5) struct base1 { int b1, b2 = 42; };struct base2 { base2() { b3 = 42; }int b3;};struct derived : base1, base2 {int d;}; derived d1{{1, 2}, {}, 4}; derived d2{{}, {}, 4}; initializesd1.b1 with 1,d1.b2 with 2,d1.b3 with 42,d1.d with 4, andd2.b1 with 0,d2.b2 with 42,d2.b3 with 42,d2.d with 4[.](#4.3.sentence-6) — *end example*] [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5628) For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows: - [(5.1)](#5.1) If the element has a default member initializer ([[class.mem]](class.mem "11.4 Class members")), the element is initialized from that initializer[.](#5.1.sentence-1) - [(5.2)](#5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization"))[.](#5.2.sentence-1) - [(5.3)](#5.3) Otherwise, the program is ill-formed[.](#5.3.sentence-1) If the aggregate is a union and the initializer list is empty, then - [(5.4)](#5.4) if any variant member has a default member initializer, that member is initialized from its default member initializer; - [(5.5)](#5.5) otherwise, the first member of the union (if any) is copy-initialized from an empty initializer list[.](#5.sentence-2) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5652) [*Example [3](#example-3)*: struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" }; initializesss.a with 1,ss.b with "asdf",ss.c with 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')[.](#6.sentence-1) struct A { string a; int b = 42; int c = -1;}; A{.c=21} has the following steps: - [(6.1)](#6.1) Initialize a with {} - [(6.2)](#6.2) Initialize b with = 42 - [(6.3)](#6.3) Initialize c with = 21 — *end example*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5685) The initializations of the elements of the aggregate are evaluated in the element order[.](#7.sentence-1) 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[.](#7.sentence-2) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5693) An aggregate that is a class can also be initialized with a single expression not enclosed in braces, as described in [[dcl.init]](dcl.init "9.5 Initializers")[.](#8.sentence-1) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5697) The destructor for each element of class type other than an anonymous union member is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors")) from the context where the aggregate initialization occurs[.](#9.sentence-1) [*Note [4](#note-4)*: This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([[except.ctor]](except.ctor "14.3 Stack unwinding"))[.](#9.sentence-2) — *end note*] [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5708) The number of elements ([[dcl.array]](dcl.array "9.3.4.5 Arrays")) in an array of unknown bound initialized with a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") is the number of explicitly initialized elements of the array[.](#10.sentence-1) [*Example [4](#example-4)*: int x[] = { 1, 3, 5 }; declares and initializesx as a one-dimensional array that has three elements since no size was specified and there are three initializers[.](#10.sentence-2) — *end example*] [*Example [5](#example-5)*: Instruct X { int i, j, k; }; X a[] = { 1, 2, 3, 4, 5, 6 }; X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };a and b have the same value[.](#10.sentence-3) — *end example*] An array of unknown bound shall not be initialized with an empty [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") {}[.](#10.sentence-4)[79](#footnote-79 "The syntax provides for empty braced-init-lists, but nonetheless C++ does not have zero length arrays.") [*Note [5](#note-5)*: A default member initializer does not determine the bound for a member array of unknown bound[.](#10.sentence-5) Since the default member initializer is ignored if a suitable [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") is present ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")), the default member initializer is not considered to initialize the array of unknown bound[.](#10.sentence-6) [*Example [6](#example-6)*: struct S {int y[] = { 0 }; // error: non-static data member of incomplete type}; — *end example*] — *end note*] [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5751) [*Note [6](#note-6)*: Static data members, non-static data members of anonymous union members, and unnamed bit-fields are not considered elements of the aggregate[.](#11.sentence-1) [*Example [7](#example-7)*: struct A {int i; static int s; int j; int :17; int k;} a = { 1, 2, 3 }; Here, the second initializer 2 initializesa.j and not the static data memberA​::​s, and the third initializer 3 initializes a.k and not the unnamed bit-field before it[.](#11.sentence-2) — *end example*] — *end note*] [12](#12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5777) 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[.](#12.sentence-1) [*Example [8](#example-8)*: struct A;extern A a;struct A {const A& a1 { A{a,a} }; // OKconst A& a2 { A{} }; // error}; A a{a,a}; // OKstruct B {int n = B{}.n; // error}; — *end example*] [13](#13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5798) When initializing a multidimensional array, the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* initialize the elements with the last (rightmost) index of the array varying the fastest ([[dcl.array]](dcl.array "9.3.4.5 Arrays"))[.](#13.sentence-1) [*Example [9](#example-9)*: int x[2][2] = { 3, 1, 4, 2 }; initializesx[0][0] to3,x[0][1] to1,x[1][0] to4, andx[1][1] to2[.](#13.sentence-2) 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[.](#13.sentence-3) — *end example*] [14](#14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5834) Each [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") in a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") is said to [*appertain*](dcl.attr.grammar#def:appertain "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") to an element of the aggregate being initialized or to an element of one of its subaggregates[.](#14.sentence-1) Considering the sequence of [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s*, and the sequence of aggregate elements initially formed as the sequence of elements of the aggregate being initialized and potentially modified as described below, each [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") appertains to the corresponding aggregate element if - [(14.1)](#14.1) the aggregate element is not an aggregate, or - [(14.2)](#14.2) the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") begins with a left brace, or - [(14.3)](#14.3) the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") is an expression and an implicit conversion sequence can be formed that converts the expression to the type of the aggregate element, or - [(14.4)](#14.4) the aggregate element is an aggregate that itself has no aggregate elements[.](#14.sentence-2) Otherwise, the aggregate element is an aggregate and that subaggregate is replaced in the list of aggregate elements by the sequence of its own aggregate elements, and the appertainment analysis resumes with the first such element and the same [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#14.sentence-3) [*Note [7](#note-7)*: These rules apply recursively to the aggregate's subaggregates[.](#14.sentence-4) [*Example [10](#example-10)*: Instruct S1 { int a, b; };struct S2 { S1 s, t; }; S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 }; S2 y[2] = {{{ 1, 2 }, { 3, 4 }}, {{ 5, 6 }, { 7, 8 }}};x and y have the same value[.](#14.sentence-5) — *end example*] — *end note*] This process continues until all [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* have been exhausted[.](#14.sentence-6) If any [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") remains that does not appertain to an element of the aggregate or one of its subaggregates, the program is ill-formed[.](#14.sentence-7) [*Example [11](#example-11)*: char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers — *end example*] [15](#15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5899) [*Example [12](#example-12)*: 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][.](#15.sentence-1) Likewise the next two lines initializey[1] andy[2][.](#15.sentence-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[.](#15.sentence-3) In the following example, braces in the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") are elided; however the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") of the above example,float y[4][3] = {1, 3, 5, 2, 4, 6, 3, 5, 7}; The initializer fory begins with a left brace, but the one fory[0] does not, therefore three elements from the list are used[.](#15.sentence-5) Likewise the next three are taken successively fory[1] andy[2][.](#15.sentence-6) — *end example*] [16](#16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5953) [*Note [8](#note-8)*: The initializer for an empty subaggregate is needed if any initializers are provided for subsequent elements[.](#16.sentence-1) [*Example [13](#example-13)*: struct S { } s;struct A { S s1; int i1; S s2; int i2; S s3; int i3;} a = {{ }, // Required initialization0, s, // Required initialization0}; // Initialization not required for A​::​s3 because A​::​i3 is also not initialized — *end example*] — *end note*] [17](#17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5977) [*Example [14](#example-14)*: struct A {int i; operator int();};struct B { A a1, a2; int z;}; A a; B b = { 4, a, a }; Braces are elided around the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") forb.a1.i[.](#17.sentence-1) b.a1.i is initialized with 4,b.a2 is initialized witha,b.z is initialized with whatevera.operator int() returns[.](#17.sentence-2) — *end example*] [18](#18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6006) [*Note [9](#note-9)*: An aggregate array or an aggregate class can contain elements of a class type with a user-declared constructor ([[class.ctor]](class.ctor "11.4.5 Constructors"))[.](#18.sentence-1) Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2 Explicit initialization")[.](#18.sentence-2) — *end note*] [19](#19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6014) [*Note [10](#note-10)*: Whether the initialization of aggregates with static storage duration is static or dynamic is specified in [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#19.sentence-1) — *end note*] [20](#20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6021) When a union is initialized with an initializer list, there shall not be more than one explicitly initialized element[.](#20.sentence-1) [*Example [15](#example-15)*: 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*] [21](#21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6039) [*Note [11](#note-11)*: As described above, the braces around the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") for a union member can be omitted if the union is a member of another aggregate[.](#21.sentence-1) — *end note*] [79)](#footnote-79)[79)](#footnoteref-79) The syntax provides for empty [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s*, but nonetheless C++ does not have zero length arrays[.](#footnote-79.sentence-1)