Files
2025-10-25 03:02:53 +03:00

504 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.2Aggregates[dcl.init.aggr]") is an array or a class ([[class]](class "11Classes")) with
- [(1.1)](#1.1)
no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5Constructors")),
- [(1.2)](#1.2)
no private or protected direct non-static data members ([[class.access]](class.access "11.8Member access control")),
- [(1.3)](#1.3)
no private or protected direct base classes ([[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")), and
- [(1.4)](#1.4)
no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")) or virtual base classes ([[class.mi]](class.mi "11.7.2Multiple 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.2Aggregates[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.4Class 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.5List-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.2Aggregates[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.1General[dcl.init.general]"),
the aggregate shall be of class type,
the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in each [*designator*](dcl.init.general#nt:designator "9.5.1General[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.1General[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.1General[dcl.init.general]"),
the element is initialized by the[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") { *D* },
where *D* is the [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[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.1General[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.1General[dcl.init.general]"),
the element is initialized with the [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") of the corresponding [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")[.](#4.2.sentence-1)
If that initializer is of the form= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and
a narrowing conversion ([[dcl.init.list]](dcl.init.list "9.5.5List-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.1General[dcl.init.general]")[.](#4.3.sentence-1)
If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[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.1General[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.1General[dcl.init.general]") consisting of all of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[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.4Class 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.5List-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.5Initializers")[.](#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.7Destructors"))
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.3Stack 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.5Arrays")) in an array of unknown bound
initialized with a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[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.1General[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.3Initializing bases and members[class.base.init]") is present ([[class.base.init]](class.base.init "11.9.3Initializing 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.1General[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.5Arrays"))[.](#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.1General[dcl.init.general]") in
a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") is said to [*appertain*](dcl.attr.grammar#def:appertain "9.13.1Attribute 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.1General[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.1General[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.1General[dcl.init.general]") begins with a left brace, or
- [(14.3)](#14.3)
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[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.1General[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.1General[dcl.init.general]")*s* have been exhausted[.](#14.sentence-6)
If any [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[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.1General[dcl.init.general]") are elided;
however the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[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.1General[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.5Constructors"))[.](#18.sentence-1)
Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2Explicit 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.2Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10Declaration 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.1General[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.1General[dcl.init.general]")*s*,
but nonetheless C++ does not have zero length arrays[.](#footnote-79.sentence-1)