[dcl.init]

# 9 Declarations [[dcl]](./#dcl)

## 9.5 Initializers [dcl.init]

### [9.5.1](#general) General [[dcl.init.general]](dcl.init.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4912)

The process of initialization described in [dcl.init] applies to
all initializations regardless of syntactic context, including the
initialization of a function parameter ([[expr.call]](expr.call "7.6.1.3 Function call")), the
initialization of a return value ([[stmt.return]](stmt.return "8.8.4 The return statement")), or when an
initializer follows a declarator[.](#general-1.sentence-1)

[initializer:](#nt:initializer "9.5.1 General [dcl.init.general]")  
[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")  
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )

[brace-or-equal-initializer:](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")  
= [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")  
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")

[initializer-clause:](#nt:initializer-clause "9.5.1 General [dcl.init.general]")  
[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")  
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")

[braced-init-list:](#nt:braced-init-list "9.5.1 General [dcl.init.general]")  
{ [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") ,opt }  
{ [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") ,opt }  
{ }

[initializer-list:](#nt:initializer-list "9.5.1 General [dcl.init.general]")  
[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt  
[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") , [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt

[designated-initializer-list:](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]")  
[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")  
[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") , [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")

[designated-initializer-clause:](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")  
[*designator*](#nt:designator "9.5.1 General [dcl.init.general]") [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")

[designator:](#nt:designator "9.5.1 General [dcl.init.general]")  
. [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")

[expr-or-braced-init-list:](#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]")  
[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")  
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")

[*Note [1](#general-note-1)*:

The rules in [dcl.init] apply even if the grammar permits only
the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") form
of [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") in a given context[.](#general-1.sentence-2)

â *end note*]

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4978)

Except for objects declared with the constexpr specifier, for which see [[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"),
an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") in the definition of a variable can consist of
arbitrary expressions involving literals and previously declared
variables and functions,
regardless of the variable's storage duration[.](#general-2.sentence-1)

[*Example [1](#general-example-1)*: int f(int);int a = 2;int b = f(a);int c(b); â *end example*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4993)

[*Note [2](#general-note-2)*:

Default arguments are more restricted; see [[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")[.](#general-3.sentence-1)

â *end note*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4998)

[*Note [3](#general-note-3)*:

The order of initialization of variables with static storage duration is described in [[basic.start]](basic.start "6.10.3 Start and termination") and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#general-4.sentence-1)

â *end note*]

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5004)

A declaration D of a variable with linkage
shall not have an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") if D inhabits a block scope[.](#general-5.sentence-1)

[6](#general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5009)

To [*zero-initialize*](#def:zero-initialization "9.5.1 General [dcl.init.general]") an object or reference of type T means:

- [(6.1)](#general-6.1)

if T is std​::​meta​::​info,
the object is initialized to a null reflection value;

- [(6.2)](#general-6.2)

if T is any other scalar type ([[basic.types.general]](basic.types.general#term.scalar.type "6.9.1 General")),
the object is initialized to the value
obtained by converting the integer literal 0 (zero) to T;[78](#footnote-78 "As specified in [conv.ptr], converting an integer literal whose value is 0 to a pointer type results in a null pointer value.")

- [(6.3)](#general-6.3)

ifT is a (possibly cv-qualified) non-union class type,
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1 General")) are initialized to zero bits and
each non-static data member,
each non-virtual base class subobject, and,
if the object is not a base class subobject,
each virtual base class subobject
is zero-initialized;

- [(6.4)](#general-6.4)

ifT is a (possibly cv-qualified) union type,
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1 General")) are initialized to zero bits and
the
object's first non-static named
data member
is zero-initialized;

- [(6.5)](#general-6.5)

ifT is an array type,
each element is zero-initialized;

- [(6.6)](#general-6.6)

ifT is a reference type, no initialization is performed[.](#general-6.sentence-1)

[7](#general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5062)

To[*default-initialize*](#def:default-initialization "9.5.1 General [dcl.init.general]") an object of typeT means:

- [(7.1)](#general-7.1)

  IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")),
constructors are considered[.](#general-7.1.sentence-1)
  The applicable constructors are
enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor")), and the best one for the[*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") () is chosen through
overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-7.1.sentence-2)
  The constructor thus selected
is called, with an empty argument list, to initialize the object[.](#general-7.1.sentence-3)

- [(7.2)](#general-7.2)

  IfT is an array type,
the semantic constraints of default-initializing a hypothetical element
shall be met and
each element is default-initialized[.](#general-7.2.sentence-1)

- [(7.3)](#general-7.3)

  If T is std​::​meta​::​info, the object is zero-initialized[.](#general-7.3.sentence-1)

- [(7.4)](#general-7.4)

  Otherwise,
no initialization is performed[.](#general-7.4.sentence-1)

[8](#general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5095)

A class type T is [*const-default-constructible*](#def:const-default-constructible "9.5.1 General [dcl.init.general]") if
default-initialization of T would invoke
a user-provided constructor of T (not inherited from a base class)
or if

- [(8.1)](#general-8.1)

each direct non-variant non-static data member M of T has a default member initializer
or, if M is of class type X (or array thereof),X is const-default-constructible,

- [(8.2)](#general-8.2)

if T is a union with at least one non-static data member,
exactly one variant member has a default member initializer,

- [(8.3)](#general-8.3)

if T is not a union,
for each anonymous union member with at least one non-static data member (if any),
exactly one non-static data member has a default member initializer, and

- [(8.4)](#general-8.4)

each potentially constructed base class of T is const-default-constructible[.](#general-8.sentence-1)

If a program calls for the default-initialization of an object of a
const-qualified type T,T shall be std​::​meta​::​  
info or a const-default-constructible class type,
or array thereof[.](#general-8.sentence-2)

[9](#general-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5123)

To[*value-initialize*](#def:value-initialization "9.5.1 General [dcl.init.general]") an object of typeT means:

- [(9.1)](#general-9.1)

  IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")), then
let C be the constructor selected to
default-initialize the object, if any[.](#general-9.1.sentence-1)
  If C is not user-provided, the object is first zero-initialized[.](#general-9.1.sentence-2)
  In all cases, the object is then default-initialized[.](#general-9.1.sentence-3)

- [(9.2)](#general-9.2)

  IfT is an array type,
the semantic constraints of value-initializing a hypothetical element
shall be met and
each element is value-initialized[.](#general-9.2.sentence-1)

- [(9.3)](#general-9.3)

  Otherwise, the object is zero-initialized[.](#general-9.3.sentence-1)

[10](#general-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5152)

A program that calls for default-initialization
or value-initialization
of an entity
of reference type is ill-formed[.](#general-10.sentence-1)

[11](#general-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5158)

[*Note [4](#general-note-4)*:

For every object with static storage duration,
static initialization ([[basic.start.static]](basic.start.static "6.10.3.2 Static initialization")) is performed
at program startup before any other initialization takes place[.](#general-11.sentence-1)

In some cases, additional initialization is done later[.](#general-11.sentence-2)

â *end note*]

[12](#general-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5166)

If no initializer is specified for an object, the object is default-initialized[.](#general-12.sentence-1)

[13](#general-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5169)

If the entity being initialized does not have class or array type, the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") in a
parenthesized initializer shall be a single expression[.](#general-13.sentence-1)

[14](#general-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5174)

The initialization that occurs in the = form of a[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") or[*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") ([[stmt.select]](stmt.select "8.5 Selection statements")),
as well as in argument passing, function return,
throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")),
handling an exception ([[except.handle]](except.handle "14.4 Handling an exception")),
and aggregate member initialization other than by a[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates")),
is called[*copy-initialization*](#def:copy-initialization "9.5.1 General [dcl.init.general]")[.](#general-14.sentence-1)

[*Note [5](#general-note-5)*:

Copy-initialization can invoke a move ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"))[.](#general-14.sentence-2)

â *end note*]

[15](#general-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5191)

The initialization that occurs

- [(15.1)](#general-15.1)

for an [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") that is a
parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") or a [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"),

- [(15.2)](#general-15.2)

for a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),

- [(15.3)](#general-15.3)

in a static_cast expression ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")),

- [(15.4)](#general-15.4)

in a functional notation type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")), and

- [(15.5)](#general-15.5)

in the [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") form of a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]")

is called[*direct-initialization*](#def:direct-initialization "9.5.1 General [dcl.init.general]")[.](#general-15.sentence-1)

[16](#general-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5204)

The semantics of initializers are as follows[.](#general-16.sentence-1)

The[*destination type*](#def:destination_type) is the cv-unqualified type of the object or reference being initialized and the[*source type*](#def:source_type) is the type of the initializer expression[.](#general-16.sentence-2)

If the initializer is not a single (possibly parenthesized) expression, the
source type is not defined[.](#general-16.sentence-3)

- [(16.1)](#general-16.1)

  If the initializer is a (non-parenthesized) [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") or is = [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"), the object or reference
is list-initialized ([[dcl.init.list]](#list "9.5.5 List-initialization"))[.](#general-16.1.sentence-1)

- [(16.2)](#general-16.2)

  If the destination type is a reference type, see [[dcl.init.ref]](#ref "9.5.4 References")[.](#general-16.2.sentence-1)

- [(16.3)](#general-16.3)

  If the destination type is an array of characters,
an array of char8_t,
an array of char16_t,
an array of char32_t,
or an array ofwchar_t,
and the initializer is a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]"), see [[dcl.init.string]](#string "9.5.3 Character arrays")[.](#general-16.3.sentence-1)

- [(16.4)](#general-16.4)

  If the initializer is (), the object is value-initialized[.](#general-16.4.sentence-1)
  [*Note [6](#general-note-6)*:
  Since() is not permitted by the syntax for[*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]"),X a(); is not the declaration of an object of classX,
but the declaration of a function taking no arguments and returning anX[.](#general-16.4.sentence-2)
  The form() can appear in certain other initialization contexts ([[expr.new]](expr.new "7.6.2.8 New"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#general-16.4.sentence-3)
 â *end note*]

- [(16.5)](#general-16.5)

  Otherwise, if the destination type is an array,
the object is initialized as follows[.](#general-16.5.sentence-1)
  The [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") shall be of the form( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )[.](#general-16.5.sentence-2)
  Let x1, …, xk be
the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")[.](#general-16.5.sentence-3)
  If the destination type is an array of unknown bound,
it is defined as having k elements[.](#general-16.5.sentence-4)
  Let n denote the array size after this potential adjustment[.](#general-16.5.sentence-5)
  If k is greater than n,
the program is ill-formed[.](#general-16.5.sentence-6)
  Otherwise, the ith array element is copy-initialized withxi for each 1 â¤ i â¤ k, and
value-initialized for each k<iâ¤n[.](#general-16.5.sentence-7)
  For each 1â¤i<jâ¤n,
every value computation and side effect associated with
the initialization of the ith element of the array
is sequenced before those associated with
the initialization of the jth element[.](#general-16.5.sentence-8)

- [(16.6)](#general-16.6)

  Otherwise, if the destination type is a class type:
  * [(16.6.1)](#general-16.6.1)

      If the initializer expression is a prvalue
and the cv-unqualified version of the source type
is the same as the destination type,
the initializer expression is used to initialize the destination object[.](#general-16.6.1.sentence-1)
      [*Example [2](#general-example-2)*:
      T x = T(T(T())); value-initializes x[.](#general-16.6.1.sentence-2)
 â *end example*]

  * [(16.6.2)](#general-16.6.2)

      Otherwise, if the initialization is direct-initialization,
or if it is copy-initialization where the cv-unqualified version of the source
type is the same as or is derived from the class of the destination type,
constructors are considered[.](#general-16.6.2.sentence-1)
      The applicable constructors
are enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor")), and the best one is chosen
through overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.6.2.sentence-2)
      Then:
    +
          [(16.6.2.1)](#general-16.6.2.1)
          If overload resolution is successful,
the selected constructor
is called to initialize the object, with the initializer
expression or [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") as its argument(s)[.](#general-16.6.2.1.sentence-1)

    +
          [(16.6.2.2)](#general-16.6.2.2)
          Otherwise, if no constructor is viable,
the destination type is
an aggregate class, and
the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
the object is initialized as follows[.](#general-16.6.2.2.sentence-1)
          Let e1, …, en be the elements of the aggregate ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#general-16.6.2.2.sentence-2)
          Let x1, …, xk be the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")[.](#general-16.6.2.2.sentence-3)
          If k is greater than n, the program is ill-formed[.](#general-16.6.2.2.sentence-4)
          The element ei is copy-initialized withxi for 1 â¤ i â¤ k[.](#general-16.6.2.2.sentence-5)
          The remaining elements are initialized with
their default member initializers, if any, and
otherwise are value-initialized[.](#general-16.6.2.2.sentence-6)
          For each 1â¤i<jâ¤n,
every value computation and side effect
associated with the initialization of ei is sequenced before those associated with the initialization of ej[.](#general-16.6.2.2.sentence-7)
          [*Note [7](#general-note-7)*:
          By contrast with direct-list-initialization,
narrowing conversions ([[dcl.init.list]](#list "9.5.5 List-initialization")) can appear,
designators are not permitted,
a temporary object bound to a reference
does not have its lifetime extended ([[class.temporary]](class.temporary "6.8.7 Temporary objects")), and
there is no brace elision[.](#general-16.6.2.2.sentence-8)
          [*Example [3](#general-example-3)*: struct A {int a; int&& r;};

            int f();int n = 10;

            A a1{1, f()}; // OK, lifetime is extended A a2(1, f()); // well-formed, but dangling reference A a3{1.0, 1}; // error: narrowing conversion A a4(1.0, 1); // well-formed, but dangling reference A a5(1.0, std::move(n)); // OK â *end example*]
 â *end note*]

    +
          [(16.6.2.3)](#general-16.6.2.3)
          Otherwise, the initialization is ill-formed[.](#general-16.6.2.3.sentence-1)

  * [(16.6.3)](#general-16.6.3)

      Otherwise (i.e., for the remaining copy-initialization cases),
user-defined conversions that can convert from the
source type to the destination type or (when a conversion function
is used) to a derived class thereof are enumerated as described in [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"),
and the best one is chosen through overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.6.3.sentence-1)
      If the conversion cannot be done or
is ambiguous, the initialization is ill-formed[.](#general-16.6.3.sentence-2)
      The function
selected is called with the initializer expression as its
argument; if the function is a constructor, the call is a prvalue
of the cv-unqualified version of the
destination type whose result object is initialized by the constructor[.](#general-16.6.3.sentence-3)
      The call is used
to direct-initialize, according to the rules above, the object
that is the destination of the copy-initialization[.](#general-16.6.3.sentence-4)

- [(16.7)](#general-16.7)

  Otherwise, if the source type
is a (possibly cv-qualified) class type, conversion functions are
considered[.](#general-16.7.sentence-1)
  The applicable conversion functions are enumerated ([[over.match.conv]](over.match.conv "12.2.2.6 Initialization by conversion function")),
and the best one is chosen through overload
resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#general-16.7.sentence-2)
  The user-defined conversion so selected
is called to convert the initializer expression into the
object being initialized[.](#general-16.7.sentence-3)
  If the conversion cannot be done or is
ambiguous, the initialization is ill-formed[.](#general-16.7.sentence-4)

- [(16.8)](#general-16.8)

  Otherwise, if the initialization is direct-initialization,
the source type is std​::​nullptr_t, and
the destination type is bool,
the initial value of the object being initialized is false[.](#general-16.8.sentence-1)

- [(16.9)](#general-16.9)

  Otherwise, the initial value of the object being initialized is
the (possibly converted) value of the initializer expression[.](#general-16.9.sentence-1)
  A standard conversion sequence ([[conv]](conv "7.3 Standard conversions")) is used
to convert the initializer expression to
a prvalue of
the destination type;
no user-defined conversions are considered[.](#general-16.9.sentence-2)
  If the conversion cannot
be done, the initialization is ill-formed[.](#general-16.9.sentence-3)
  When initializing a bit-field with a value that it cannot represent, the
resulting value of the bit-field isimplementation-defined[.](#general-16.9.sentence-4)
  [*Note [8](#general-note-8)*:
  An expression of type
â*cv1* Tâ
can initialize an object of type
â*cv2* Tâ
independently of
the cv-qualifiers*cv1* and *cv2*[.](#general-16.9.sentence-5)
  int a;const int b = a;int c = b; â *end note*]

[17](#general-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5407)

An immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")) that is not evaluated where
it appears ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"), [[class.mem.general]](class.mem.general "11.4.1 General"))
is evaluated and checked for whether it is
a constant expression at the point where
the enclosing [*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") is used in
a function call, a constructor definition, or an aggregate initialization[.](#general-17.sentence-1)

[18](#general-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5415)

An [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") followed by an ellipsis is a
pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#general-18.sentence-1)

[19](#general-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5419)

Initialization includes
the evaluation of all subexpressions of
each [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") of
the initializer (possibly nested within [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s*) and
the creation of any temporary objects for
function arguments or return values ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#general-19.sentence-1)

[20](#general-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5427)

If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),
the expressions are evaluated in the order
specified for function calls ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#general-20.sentence-1)

[21](#general-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5432)

The same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") shall not appear in multiple [*designator*](#nt:designator "9.5.1 General [dcl.init.general]")*s* of a[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]")[.](#general-21.sentence-1)

[22](#general-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5437)

An object whose initialization has completed
is deemed to be constructed,
even if the object is of non-class type or
no constructor of the object's class
is invoked for the initialization[.](#general-22.sentence-1)

[*Note [9](#general-note-9)*:

Such an object might have been value-initialized
or initialized by aggregate initialization ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))
or by an inherited constructor ([[class.inhctor.init]](class.inhctor.init "11.9.4 Initialization by inherited constructor"))[.](#general-22.sentence-2)

â *end note*]

Destroying an object of class type invokes the destructor of the class[.](#general-22.sentence-3)

Destroying a scalar type has no effect other than
ending the lifetime of the object ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#general-22.sentence-4)

Destroying an array destroys each element in reverse subscript order[.](#general-22.sentence-5)

[23](#general-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5453)

A declaration that specifies the initialization of a variable,
whether from an explicit initializer or by default-initialization,
is called the [*initializing declaration*](#def:initializing_declaration "9.5.1 General [dcl.init.general]") of that variable[.](#general-23.sentence-1)

[*Note [10](#general-note-10)*:

In most cases
this is the defining declaration ([[basic.def]](basic.def "6.2 Declarations and definitions")) of the variable,
but the initializing declaration
of a non-inline static data member ([[class.static.data]](class.static.data "11.4.9.3 Static data members"))
can be the declaration within the class definition
and not the definition (if any) outside it[.](#general-23.sentence-2)

â *end note*]

[78)](#footnote-78)[78)](#footnoteref-78)

As specified in [[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"), converting an integer
literal whose value is0 to a pointer type results in a null pointer value[.](#footnote-78.sentence-1)

### [9.5.2](#aggr) Aggregates [[dcl.init.aggr]](dcl.init.aggr)

[1](#aggr-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)](#aggr-1.1)

no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5 Constructors")),

- [(1.2)](#aggr-1.2)

no private or protected direct non-static data members ([[class.access]](class.access "11.8 Member access control")),

- [(1.3)](#aggr-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)](#aggr-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"))[.](#aggr-1.sentence-1)

[*Note [1](#aggr-note-1)*:

Aggregate initialization does not allow accessing
protected and private base class' members or constructors[.](#aggr-1.sentence-2)

â *end note*]

[2](#aggr-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)](#aggr-2.1)

for an array, the array elements in increasing subscript order, or

- [(2.2)](#aggr-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[.](#aggr-2.sentence-1)

[3](#aggr-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]](#list "9.5.5 List-initialization"),
the elements of the initializer list are taken as initializers
for the elements of the aggregate[.](#aggr-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)](#aggr-3.1)

  If the initializer list is
a brace-enclosed [*designated-initializer-list*](#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*](#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[.](#aggr-3.1.sentence-1)

- [(3.2)](#aggr-3.2)

  If the initializer list is a brace-enclosed [*initializer-list*](#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)[.](#aggr-3.2.sentence-1)

- [(3.3)](#aggr-3.3)

  Otherwise, the initializer list must be {},
and there are no explicitly initialized elements[.](#aggr-3.3.sentence-1)

[4](#aggr-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5529)

For each explicitly initialized element:

- [(4.1)](#aggr-4.1)

  If the element is an anonymous union member and
the initializer list is
a brace-enclosed [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"),
the element is initialized by the[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") { *D* },
where *D* is the [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") naming a member of the anonymous union member[.](#aggr-4.1.sentence-1)
  There shall be only one such [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-4.1.sentence-2)
  [*Example [1](#aggr-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[.](#aggr-4.1.sentence-3)
 â *end example*]

- [(4.2)](#aggr-4.2)

  Otherwise, if the initializer list is
a brace-enclosed [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]"),
the element is initialized with the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") of the corresponding [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-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]](#list "9.5.5 List-initialization")) is required
to convert the expression, the program is ill-formed[.](#aggr-4.2.sentence-2)
  [*Note [2](#aggr-note-2)*:
  The form of the initializer determines
whether copy-initialization or direct-initialization is performed[.](#aggr-4.2.sentence-3)
 â *end note*]

- [(4.3)](#aggr-4.3)

  Otherwise,
the initializer list is a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]")[.](#aggr-4.3.sentence-1)
  If an [*initializer-clause*](#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*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-4.3.sentence-2)
  Otherwise,
the aggregate element is copy-initialized
from a brace-enclosed [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") consisting of all of the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* that appertain to subobjects of the aggregate element,
in the order of appearance[.](#aggr-4.3.sentence-3)
  [*Note [3](#aggr-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[.](#aggr-4.3.sentence-4)
 â *end note*]
  [*Example [2](#aggr-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[.](#aggr-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[.](#aggr-4.3.sentence-6)
 â *end example*]

[5](#aggr-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)](#aggr-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[.](#aggr-5.1.sentence-1)

- [(5.2)](#aggr-5.2)

  Otherwise, if the element is not a reference, the element
is copy-initialized from an empty initializer list ([[dcl.init.list]](#list "9.5.5 List-initialization"))[.](#aggr-5.2.sentence-1)

- [(5.3)](#aggr-5.3)

  Otherwise, the program is ill-formed[.](#aggr-5.3.sentence-1)

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

- [(5.4)](#aggr-5.4)

if any variant member has a default member initializer,
that member is initialized from its default member initializer;

- [(5.5)](#aggr-5.5)

otherwise, the first member of the union (if any)
is copy-initialized from an empty initializer list[.](#aggr-5.sentence-2)

[6](#aggr-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5652)

[*Example [3](#aggr-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')[.](#aggr-6.sentence-1)

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

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

- [(6.1)](#aggr-6.1)

Initialize a with {}

- [(6.2)](#aggr-6.2)

Initialize b with = 42

- [(6.3)](#aggr-6.3)

Initialize c with = 21

â *end example*]

[7](#aggr-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[.](#aggr-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[.](#aggr-7.sentence-2)

[8](#aggr-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][.](#aggr-8.sentence-1)

[9](#aggr-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[.](#aggr-9.sentence-1)

[*Note [4](#aggr-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"))[.](#aggr-9.sentence-2)

â *end note*]

[10](#aggr-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*](#nt:initializer-list "9.5.1 General [dcl.init.general]") is the number of explicitly initialized elements of the array[.](#aggr-10.sentence-1)

[*Example [4](#aggr-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[.](#aggr-10.sentence-2)

â *end example*]

[*Example [5](#aggr-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[.](#aggr-10.sentence-3)

â *end example*]

An array of unknown bound shall not be initialized with
an empty [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") {}[.](#aggr-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](#aggr-note-5)*:

A default member initializer does not determine the bound for a member
array of unknown bound[.](#aggr-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[.](#aggr-10.sentence-6)

[*Example [6](#aggr-example-6)*: struct S {int y[] = { 0 }; // error: non-static data member of incomplete type}; â *end example*]

â *end note*]

[11](#aggr-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5751)

[*Note [6](#aggr-note-6)*:

Static data members,
non-static data members of anonymous union members,
and
unnamed bit-fields
are not considered elements of the aggregate[.](#aggr-11.sentence-1)

[*Example [7](#aggr-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[.](#aggr-11.sentence-2)

â *end example*]

â *end note*]

[12](#aggr-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[.](#aggr-12.sentence-1)

[*Example [8](#aggr-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](#aggr-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5798)

When initializing a multidimensional array,
the[*initializer-clause*](#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"))[.](#aggr-13.sentence-1)

[*Example [9](#aggr-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[.](#aggr-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[.](#aggr-13.sentence-3)

â *end example*]

[14](#aggr-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5834)

Each [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") in
a brace-enclosed [*initializer-list*](#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[.](#aggr-14.sentence-1)

Considering the sequence of [*initializer-clause*](#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*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") appertains to
the corresponding aggregate element if

- [(14.1)](#aggr-14.1)

the aggregate element is not an aggregate, or

- [(14.2)](#aggr-14.2)

the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") begins with a left brace, or

- [(14.3)](#aggr-14.3)

the [*initializer-clause*](#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)](#aggr-14.4)

the aggregate element is an aggregate that itself has no aggregate elements[.](#aggr-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*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#aggr-14.sentence-3)

[*Note [7](#aggr-note-7)*:

These rules apply recursively to the aggregate's subaggregates[.](#aggr-14.sentence-4)

[*Example [10](#aggr-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[.](#aggr-14.sentence-5)

â *end example*]

â *end note*]

This process continues
until all [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* have been exhausted[.](#aggr-14.sentence-6)

If any [*initializer-clause*](#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[.](#aggr-14.sentence-7)

[*Example [11](#aggr-example-11)*: char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers â *end example*]

[15](#aggr-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5899)

[*Example [12](#aggr-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][.](#aggr-15.sentence-1)

Likewise the next two lines initializey[1] andy[2][.](#aggr-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[.](#aggr-15.sentence-3)

In the following example, braces in the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") are elided;
however the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](#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[.](#aggr-15.sentence-5)

Likewise the next three are taken successively fory[1] andy[2][.](#aggr-15.sentence-6)

â *end example*]

[16](#aggr-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5953)

[*Note [8](#aggr-note-8)*:

The initializer for an empty subaggregate is needed
if any initializers are provided for subsequent elements[.](#aggr-16.sentence-1)

[*Example [13](#aggr-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](#aggr-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5977)

[*Example [14](#aggr-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*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") forb.a1.i[.](#aggr-17.sentence-1)

b.a1.i is initialized with 4,b.a2 is initialized witha,b.z is initialized with whatevera.operator int() returns[.](#aggr-17.sentence-2)

â *end example*]

[18](#aggr-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6006)

[*Note [9](#aggr-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"))[.](#aggr-18.sentence-1)

Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2 Explicit initialization")[.](#aggr-18.sentence-2)

â *end note*]

[19](#aggr-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6014)

[*Note [10](#aggr-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")[.](#aggr-19.sentence-1)

â *end note*]

[20](#aggr-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[.](#aggr-20.sentence-1)

[*Example [15](#aggr-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](#aggr-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6039)

[*Note [11](#aggr-note-11)*:

As described above,
the braces around the[*initializer-clause*](#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[.](#aggr-21.sentence-1)

â *end note*]

[79)](#footnote-79)[79)](#footnoteref-79)

The syntax provides for empty [*braced-init-list*](#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)

### [9.5.3](#string) Character arrays [[dcl.init.string]](dcl.init.string)

[1](#string-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6051)

An array of ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")),char8_t array,char16_t array,char32_t array,
or wchar_t array
may be initialized by
an ordinary string literal,
UTF-8 string literal,
UTF-16 string literal,
UTF-32 string literal, or
wide string literal,
respectively, or by an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") enclosed in
braces ([[lex.string]](lex.string "5.13.5 String literals"))[.](#string-1.sentence-1)

Additionally, an array of char orunsigned char may be initialized by
a UTF-8 string literal, or by
such a string literal enclosed in braces[.](#string-1.sentence-2)

Successive
characters of the
value of the [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") initialize the elements of the array,
with an integral conversion ([[conv.integral]](conv.integral "7.3.9 Integral conversions"))
if necessary for the source and destination value[.](#string-1.sentence-3)

[*Example [1](#string-example-1)*:

char msg[] = "Syntax error on line %s\n"; shows a character array whose members are initialized
with a[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")[.](#string-1.sentence-4)

Note that because'\n' is a single character and
because a trailing'\0' is appended,sizeof(msg) is25[.](#string-1.sentence-5)

â *end example*]

[2](#string-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6098)

There shall not be more initializers than there are array elements[.](#string-2.sentence-1)

[*Example [2](#string-example-2)*:

char cv[4] = "asdf"; // error is ill-formed since there is no space for the implied trailing'\0'[.](#string-2.sentence-2)

â *end example*]

[3](#string-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6108)

If there are fewer initializers than there are array elements, each element not
explicitly initialized shall be zero-initialized ([dcl.init])[.](#string-3.sentence-1)

### [9.5.4](#ref) References [[dcl.init.ref]](dcl.init.ref)

[1](#ref-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6115)

A variable whose declared type is
âreference to Tâ ([[dcl.ref]](dcl.ref "9.3.4.3 References"))
shall be initialized[.](#ref-1.sentence-1)

[*Example [1](#ref-example-1)*: int g(int) noexcept;void f() {int i; int& r = i; // r refers to i r = 1; // the value of i becomes 1int* p = &r; // p points to iint& rr = r; // rr refers to what r refers to, that is, to iint (&rg)(int) = g; // rg refers to the function g rg(i); // calls function gint a[3]; int (&ra)[3] = a; // ra refers to the array a ra[1] = i; // modifies a[1]} â *end example*]

[2](#ref-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6137)

A reference cannot be changed to refer to another object after initialization[.](#ref-2.sentence-1)

[*Note [1](#ref-note-1)*:

Assignment to a reference assigns to the object referred to by the reference ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#ref-2.sentence-2)

â *end note*]

Argument passing ([[expr.call]](expr.call "7.6.1.3 Function call"))and function value return ([[stmt.return]](stmt.return "8.8.4 The return statement")) are initializations[.](#ref-2.sentence-3)

[3](#ref-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6148)

The initializer can be omitted for a reference only in a parameter declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
in the declaration of a function return type, in the declaration of
a class member within its class definition ([[class.mem]](class.mem "11.4 Class members")), and where theextern specifier is explicitly used[.](#ref-3.sentence-1)

[*Example [2](#ref-example-2)*: int& r1; // error: initializer missingextern int& r2; // OK â *end example*]

[4](#ref-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6162)

Given types â*cv1* T1â and â*cv2* T2â,
â*cv1* T1â is [*reference-related*](#def:reference-related "9.5.4 References [dcl.init.ref]") to
â*cv2* T2â ifT1 is similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to T2, orT1 is a base class of T2[.](#ref-4.sentence-1)

â*cv1* T1â is [*reference-compatible*](#def:reference-compatible "9.5.4 References [dcl.init.ref]") with â*cv2* T2â if
a prvalue of type âpointer to *cv2* T2â can be converted to
the type âpointer to *cv1* T1â
via a standard conversion sequence ([[conv]](conv "7.3 Standard conversions"))[.](#ref-4.sentence-2)

In all cases where the reference-compatible relationship
of two types is used to establish the validity of a reference binding and
the standard conversion sequence would be ill-formed,
a program that necessitates such a binding is ill-formed[.](#ref-4.sentence-3)

[5](#ref-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6178)

A reference to type â*cv1* T1â is initialized by
an expression of type â*cv2* T2â as follows:

- [(5.1)](#ref-5.1)

  If the reference is an lvalue reference and the initializer expression
  * [(5.1.1)](#ref-5.1.1)

is an lvalue (but is not a
bit-field), and
â*cv1* T1â is reference-compatible with
â*cv2* T2â, or

  * [(5.1.2)](#ref-5.1.2)

has a class type (i.e.,T2 is a class type), where T1 is not reference-related to T2, and can be converted
to an lvalue of type â*cv3* T3â, where
â*cv1* T1â is reference-compatible with
â*cv3* T3â[80](#footnote-80 "This requires a conversion function ([class.conv.fct]) returning a reference type.") (this conversion is selected by enumerating the applicable conversion
functions ([[over.match.ref]](over.match.ref "12.2.2.7 Initialization by conversion function for direct reference binding")) and choosing the best one through [overload
resolution](over.match "12.2 Overload resolution [over.match]")),

then the reference binds to the initializer expression lvalue in the
first case and to the lvalue result of the conversion
in the second case (or, in either case, to the appropriate base class subobject of the object)[.](#ref-5.1.sentence-1)
  [*Note [2](#ref-note-2)*:
  The usual [lvalue-to-rvalue](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
and [function-to-pointer](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") standard
conversions are not needed, and therefore are suppressed, when such
direct bindings to lvalues are done[.](#ref-5.1.sentence-2)
 â *end note*]
  [*Example [3](#ref-example-3)*: double d = 2.0;double& rd = d; // rd refers to dconst double& rcd = d; // rcd refers to dstruct A { };struct B : A { operator int&(); } b;
A& ra = b; // ra refers to A subobject in bconst A& rca = b; // rca refers to A subobject in bint& ir = B(); // ir refers to the result of B​::​operator int& â *end example*]

- [(5.2)](#ref-5.2)

  Otherwise,
if the reference is an lvalue reference to a
type that is not const-qualified or is volatile-qualified,
the program is ill-formed[.](#ref-5.2.sentence-1)
  [*Example [4](#ref-example-4)*: double& rd2 = 2.0; // error: not an lvalue and reference not constint i = 2;double& rd3 = i; // error: type mismatch and reference not const â *end example*]

- [(5.3)](#ref-5.3)

  Otherwise, if the initializer expression
  * [(5.3.1)](#ref-5.3.1)

is an rvalue (but not a bit-field) or an lvalue of function type and
â*cv1* T1â is
reference-compatible with â*cv2* T2â, or

  * [(5.3.2)](#ref-5.3.2)

has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to
an rvalue of type â*cv3* T3â or
an lvalue of function type â*cv3* T3â,
where â*cv1* T1â is
reference-compatible with â*cv3* T3â (see [[over.match.ref]](over.match.ref "12.2.2.7 Initialization by conversion function for direct reference binding")),

then
the initializer expression in the first case and
the converted expression in the second case
is called the converted initializer[.](#ref-5.3.sentence-1)
  If the converted initializer is a prvalue,
let its type be denoted by T4;
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion")) is applied,
considering the type of the prvalue to be
â*cv1* T4â ([[conv.qual]](conv.qual "7.3.6 Qualification conversions"))[.](#ref-5.3.sentence-2)
  In any case,
the reference binds to the resulting glvalue
(or to an appropriate base class subobject)[.](#ref-5.3.sentence-3)
  [*Example [5](#ref-example-5)*: struct A { };struct B : A { } b;extern B f();const A& rca2 = f(); // binds to the A subobject of the B rvalue. A&& rra = f(); // same as abovestruct X {operator B(); operator int&();} x;const A& r = x; // binds to the A subobject of the result of the conversionint i2 = 42;int&& rri = static_cast<int&&>(i2); // binds directly to i2 B&& rrb = x; // binds directly to the result of operator Bconstexpr int f() {const int &x = 42; const_cast<int &>(x) = 1; // undefined behaviorreturn x;}constexpr int z = f(); // error: not a constant expressiontypedef int *AP[3]; // array of 3 pointer to inttypedef const int *const ACPC[3]; // array of 3 const pointer to const int ACPC &&r = AP{}; // binds directly â *end example*]

- [(5.4)](#ref-5.4)

  Otherwise, T1 shall not be reference-related to T2[.](#ref-5.4.sentence-1)

  * [(5.4.1)](#ref-5.4.1)

      If T1 or T2 is a class type,
user-defined conversions are considered
using the rules for copy-initialization of an object of type
â*cv1* T1â by
user-defined conversion ([dcl.init], [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"), [[over.match.conv]](over.match.conv "12.2.2.6 Initialization by conversion function"));
the program is ill-formed if the corresponding non-reference
copy-initialization would be ill-formed[.](#ref-5.4.1.sentence-1)
      The result E of the call to the
conversion function, as described for the non-reference
copy-initialization, is then used to direct-initialize the reference
using the form (E)[.](#ref-5.4.1.sentence-2)
      For this direct-initialization, user-defined conversions are not considered[.](#ref-5.4.1.sentence-3)

  * [(5.4.2)](#ref-5.4.2)

      Otherwise,
the initializer expression is implicitly converted to a prvalue
of type âT1â[.](#ref-5.4.2.sentence-1)
      The temporary materialization conversion is applied,
considering the type of the prvalue to be â*cv1* T1â,
and the reference is bound to the result[.](#ref-5.4.2.sentence-2)

  [*Example [6](#ref-example-6)*: struct Banana { };struct Enigma { operator const Banana(); };struct Alaska { operator Banana&(); };void enigmatic() {typedef const Banana ConstBanana;
 Banana &&banana1 = ConstBanana(); // error Banana &&banana2 = Enigma(); // error Banana &&banana3 = Alaska(); // error}const double& rcd2 = 2; // rcd2 refers to temporary with type const double and value 2.0double&& rrd = 2; // rrd refers to temporary with value 2.0const volatile int cvi = 1;const int& r2 = cvi; // error: cv-qualifier droppedstruct A { operator volatile int&(); } a;const int& r3 = a; // error: cv-qualifier dropped// from result of conversion functiondouble d2 = 1.0;double&& rrd2 = d2; // error: initializer is lvalue of reference-related typestruct X { operator int&(); };int&& rri2 = X(); // error: result of conversion function is// lvalue of reference-related typeint i3 = 2;double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0 â *end example*]

In all cases except the last
(i.e., implicitly converting the initializer expression
to the referenced type),
the reference is said to [*bind directly*](#def:bind_directly "9.5.4 References [dcl.init.ref]") to the
initializer expression[.](#ref-5.sentence-2)

[6](#ref-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6358)

[*Note [3](#ref-note-3)*:

[[class.temporary]](class.temporary "6.8.7 Temporary objects") describes the lifetime of temporaries bound to references[.](#ref-6.sentence-1)

â *end note*]

[80)](#footnote-80)[80)](#footnoteref-80)

This requires a conversion
function ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")) returning a reference type[.](#footnote-80.sentence-1)

### [9.5.5](#list) List-initialization [[dcl.init.list]](dcl.init.list)

[1](#list-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6366)

[*List-initialization*](#def:list-initialization "9.5.5 List-initialization [dcl.init.list]") is initialization of an object or reference from a[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")[.](#list-1.sentence-1)

Such an initializer is called an [*initializer list*](#def:initializer_list), and
the comma-separated[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* of the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") or[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") are called the [*elements*](#def:elements) of the initializer list[.](#list-1.sentence-2)

An initializer list may be empty[.](#list-1.sentence-3)

List-initialization can occur in direct-initialization or copy-initialization contexts;
list-initialization in a direct-initialization context is called[*direct-list-initialization*](#def:direct-list-initialization "9.5.5 List-initialization [dcl.init.list]") and list-initialization in a
copy-initialization context is called [*copy-list-initialization*](#def:copy-list-initialization "9.5.5 List-initialization [dcl.init.list]")[.](#list-1.sentence-4)

Direct-initialization that is not list-initialization is called[*direct-non-list-initialization*](#def:direct-non-list-initialization "9.5.5 List-initialization [dcl.init.list]")[.](#list-1.sentence-5)

[*Note [1](#list-note-1)*:

List-initialization can be used

- [(1.1)](#list-1.1)

as the initializer in a variable definition ([dcl.init]),

- [(1.2)](#list-1.2)

as the initializer in a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),

- [(1.3)](#list-1.3)

in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")),

- [(1.4)](#list-1.4)

as a [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") ([[stmt.iter]](stmt.iter "8.6 Iteration statements")),

- [(1.5)](#list-1.5)

as a function argument ([[expr.call]](expr.call "7.6.1.3 Function call")),

- [(1.6)](#list-1.6)

as a template argument ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments")),

- [(1.7)](#list-1.7)

as a subscript ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")),

- [(1.8)](#list-1.8)

as an argument to a constructor invocation ([dcl.init], [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")),

- [(1.9)](#list-1.9)

as an initializer for a non-static data member ([[class.mem]](class.mem "11.4 Class members")),

- [(1.10)](#list-1.10)

in a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")), or

- [(1.11)](#list-1.11)

on the right-hand side of an assignment ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#list-1.sentence-6)

[*Example [1](#list-example-1)*: int a = {1};
std::complex<double> z{1,2};new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements f( {"Nicholas","Annemarie"} ); // pass list of two elementsreturn { "Norah" }; // return list of one elementint* e {}; // initialization to zero / null pointer x = double{1}; // explicitly construct a double std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; â *end example*]

â *end note*]

[2](#list-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6413)

A constructor is an [*initializer-list constructor*](#def:initializer-list_constructor "9.5.5 List-initialization [dcl.init.list]") if its first parameter is
of type std​::​initializer_list<E> or reference tocv std​::​initializer_list<E> for some type E, and either there are no other
parameters or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#list-2.sentence-1)

[*Note [2](#list-note-2)*:

Initializer-list constructors are favored over other constructors in
list-initialization ([[over.match.list]](over.match.list "12.2.2.8 Initialization by list-initialization"))[.](#list-2.sentence-2)

Passing an initializer list as the argument
to the constructor template template<class T> C(T) of a class C does not
create an initializer-list constructor, because an initializer list argument causes the
corresponding parameter to be a non-deduced context ([[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"))[.](#list-2.sentence-3)

â *end note*]

The templatestd​::​initializer_list is not predefined;
if a standard library declaration ([[initializer.list.syn]](initializer.list.syn "17.11.2 Header <initializer_­list> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
of std​::​initializer_list is not reachable from ([[module.reach]](module.reach "10.7 Reachability"))
a use of std​::​initializer_list â
even an implicit use in which the type is not named ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")) â
the program is ill-formed[.](#list-2.sentence-4)

[3](#list-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6433)

List-initialization of an object or reference of type *cv* T is defined as follows:

- [(3.1)](#list-3.1)

  If the [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") contains a [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") andT is not a reference type,T shall be an aggregate class[.](#list-3.1.sentence-1)
  The ordered [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* in the [*designator*](#nt:designator "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") shall form a subsequence
of the ordered [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* in the direct non-static data members of T[.](#list-3.1.sentence-2)
  Aggregate initialization is performed ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#list-3.1.sentence-3)
  [*Example [2](#list-example-2)*: struct A { int x; int y; int z; };
A a{.y = 2, .x = 1}; // error: designator order does not match declaration order A b{.x = 1, .z = 2}; // OK, b.y initialized to 0 â *end example*]

- [(3.2)](#list-3.2)

  If T is an aggregate class and the initializer list has a single element
of type *cv1* U,
where U is T or a class derived from T,
the object is initialized from that element (by copy-initialization for
copy-list-initialization, or by direct-initialization for
direct-list-initialization)[.](#list-3.2.sentence-1)

- [(3.3)](#list-3.3)

  Otherwise, if T is a character array and the initializer list has a
single element that is an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") ([[dcl.init.string]](#string "9.5.3 Character arrays")),
initialization is performed as described in that subclause[.](#list-3.3.sentence-1)

- [(3.4)](#list-3.4)

  Otherwise, if T is an aggregate, aggregate initialization is
performed ([[dcl.init.aggr]](#aggr "9.5.2 Aggregates"))[.](#list-3.4.sentence-1)
  [*Example [3](#list-example-3)*: double ad[] = { 1, 2.0 }; // OKint ai[] = { 1, 2.0 }; // error: narrowingstruct S2 {int m1; double m2, m3;};
S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing S2 s23 { }; // OK, default to 0,0,0 â *end example*]

- [(3.5)](#list-3.5)

  Otherwise, if the initializer list has no elements and T is a class type with a
default constructor, the object is value-initialized[.](#list-3.5.sentence-1)

- [(3.6)](#list-3.6)

  Otherwise, if T is a specialization of std​::​initializer_list,
the object is constructed as described below[.](#list-3.6.sentence-1)

- [(3.7)](#list-3.7)

  Otherwise, if T is a class type, constructors are considered[.](#list-3.7.sentence-1)
  The applicable constructors are enumerated and
the best one is chosen through overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.match.list]](over.match.list "12.2.2.8 Initialization by list-initialization"))[.](#list-3.7.sentence-2)
  If a narrowing
conversion (see below) is required to convert any of the arguments, the program is
ill-formed[.](#list-3.7.sentence-3)
  [*Example [4](#list-example-4)*: struct S { S(std::initializer_list<double>); // #1 S(std::initializer_list<int>); // #2 S(std::initializer_list<S>); // #3 S(); // #4// ...};
S s1 = { 1.0, 2.0, 3.0 }; // invoke #1 S s2 = { 1, 2, 3 }; // invoke #2 S s3{s2}; // invoke #3 (not the copy constructor) S s4 = { }; // invoke #4 â *end example*]
  [*Example [5](#list-example-5)*: struct Map { Map(std::initializer_list<std::pair<std::string,int>>);};
Map ship = {{"Sophie",14}, {"Surprise",28}}; â *end example*]
  [*Example [6](#list-example-6)*: struct S {// no initializer-list constructors S(int, double, double); // #1 S(); // #2// ...};
S s1 = { 1, 2, 3.0 }; // OK, invoke #1 S s2 { 1.0, 2, 3 }; // error: narrowing S s3 { }; // OK, invoke #2 â *end example*]

- [(3.8)](#list-3.8)

  Otherwise, if T is an enumeration
with a fixed underlying type ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) U,
the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") has a single element v of scalar type,v can be implicitly converted to U, and
the initialization is direct-list-initialization,
the object is initialized with the value T(v) ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"));
if a narrowing conversion is required to convert v to U, the program is ill-formed[.](#list-3.8.sentence-1)
  [*Example [7](#list-example-7)*: enum byte : unsigned char { };
byte b { 42 }; // OK byte c = { 42 }; // error byte d = byte{ 42 }; // OK; same value as b byte e { -1 }; // errorstruct A { byte b; };
A a1 = { { 42 } }; // error A a2 = { byte{ 42 } }; // OKvoid f(byte);
f({ 42 }); // errorenum class Handle : uint32_t { Invalid = 0 };
Handle h { 42 }; // OK â *end example*]

- [(3.9)](#list-3.9)

  Otherwise, if
the initializer list
is not a [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") and
has a single element of type E and eitherT is not a reference type or its referenced type is
reference-related to E, the object or reference is initialized
from that element (by copy-initialization for copy-list-initialization,
or by direct-initialization for direct-list-initialization);
if a narrowing conversion (see below) is required
to convert the element to T, the program is ill-formed[.](#list-3.9.sentence-1)
  [*Example [8](#list-example-8)*: int x1 {2}; // OKint x2 {2.0}; // error: narrowing â *end example*]

- [(3.10)](#list-3.10)

  Otherwise, if T is a reference type, a prvalue is generated[.](#list-3.10.sentence-1)
  The prvalue initializes its result object by copy-list-initialization from the initializer list[.](#list-3.10.sentence-2)
  The prvalue is then used to direct-initialize the reference[.](#list-3.10.sentence-3)
  The type of the prvalue is the type referenced by T,
unless T is âreference to array of unknown bound of Uâ,
in which case the type of the prvalue is
the type of x in the declaration U x[] H,
where H is the initializer list[.](#list-3.10.sentence-4)
  [*Note [3](#list-note-3)*:
  As usual, the binding will fail and the program is ill-formed if
the reference type is an lvalue reference to a non-const type[.](#list-3.10.sentence-5)
 â *end note*]
  [*Example [9](#list-example-9)*: struct S { S(std::initializer_list<double>); // #1 S(const std::string&); // #2// ...};const S& r1 = { 1, 2, 3.0 }; // OK, invoke #1const S& r2 { "Spinach" }; // OK, invoke #2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalueconst int& i1 = { 1 }; // OKconst int& i2 = { 1.1 }; // error: narrowingconst int (&iar)[2] = { 1, 2 }; // OK, iar is bound to temporary arraystruct A { } a;struct B { explicit B(const A&); };const B& b2{a}; // error: cannot copy-list-initialize B temporary from Astruct C { int x; };
C&& c = { .x = 1 }; // OK â *end example*]

- [(3.11)](#list-3.11)

  Otherwise, if the initializer list has no elements, the object is
value-initialized[.](#list-3.11.sentence-1)
  [*Example [10](#list-example-10)*: int** pp {}; // initialized to null pointer â *end example*]

- [(3.12)](#list-3.12)

  Otherwise, the program is ill-formed[.](#list-3.12.sentence-1)
  [*Example [11](#list-example-11)*: struct A { int i; int j; };
A a1 { 1, 2 }; // aggregate initialization A a2 { 1.2 }; // error: narrowingstruct B { B(std::initializer_list<int>);};
B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor B b2 { 1, 2.0 }; // error: narrowingstruct C { C(int i, double j);};
C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) C c2 = { 1.1, 2 }; // error: narrowingint j { 1 }; // initialize to 1int k { }; // initialize to 0 â *end example*]

[4](#list-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6651)

Within the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") of a [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
the [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s*, including any that result from pack
expansions ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), are evaluated in the order in which they
appear[.](#list-4.sentence-1)

That is, every value computation and side effect associated with a
given [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") is sequenced before every value
computation and side effect associated with any [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") that follows it in the comma-separated list of the [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]")[.](#list-4.sentence-2)

[*Note [4](#list-note-4)*:

This evaluation ordering holds regardless of the semantics of the
initialization; for example, it applies when the elements of the[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") are interpreted as arguments of a constructor
call, even though ordinarily there are no sequencing constraints on the
arguments of a call[.](#list-4.sentence-3)

â *end note*]

[5](#list-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6667)

An object of type std​::​initializer_list<E> is constructed from
an initializer list as if
the implementation generated and materialized ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"))
a prvalue of type âarray of N const Eâ,
where N is the number of elements in the initializer list;
this is called the initializer list's [*backing array*](#def:array,backing "9.5.5 List-initialization [dcl.init.list]")[.](#list-5.sentence-1)

Each element of the backing array is copy-initialized with the
corresponding element of the initializer list, and thestd​::​initializer_list<E> object is constructed to refer to that array[.](#list-5.sentence-2)

[*Note [5](#list-note-5)*:

A constructor or conversion function selected for the copy needs to be
accessible ([[class.access]](class.access "11.8 Member access control")) in the context of the initializer list[.](#list-5.sentence-3)

â *end note*]

If a narrowing conversion is required to initialize any of the elements,
the program is ill-formed[.](#list-5.sentence-4)

[*Note [6](#list-note-6)*:

Backing arrays are potentially non-unique objects ([[intro.object]](intro.object "6.8.2 Object model"))[.](#list-5.sentence-5)

â *end note*]

[6](#list-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6687)

The backing array has the same lifetime as any other temporary
object ([[class.temporary]](class.temporary "6.8.7 Temporary objects")), except that initializing aninitializer_list object from the array extends the lifetime of
the array exactly like binding a reference to a temporary[.](#list-6.sentence-1)

[*Example [12](#list-example-12)*: void f(std::initializer_list<double> il);void g(float x) { f({1, x, 3});}void h() { f({1, 2, 3});}struct A {mutable int i;};void q(std::initializer_list<A>);void r() { q({A{1}, A{2}, A{3}});}

The initialization will be implemented in a way roughly equivalent to this:void g(float x) {const double __a[3] = {double{1}, double{x}, double{3}}; // backing array f(std::initializer_list<double>(__a, __a+3));}void h() {static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array f(std::initializer_list<double>(__b, __b+3));}void r() {const A __c[3] = {A{1}, A{2}, A{3}}; // backing array q(std::initializer_list<A>(__c, __c+3));} assuming that the implementation
can construct an initializer_list object with a pair of pointers, and
with the understanding that __b does not outlive the call to f[.](#list-6.sentence-2)

â *end example*]

[*Example [13](#list-example-13)*: typedef std::complex<double> cmplx;
std::vector<cmplx> v1 = { 1, 2, 3 };

void f() { std::vector<cmplx> v2{ 1, 2, 3 };
 std::initializer_list<int> i3 = { 1, 2, 3 };}struct A { std::initializer_list<int> i4;
 A() : i4{ 1, 2, 3 } {} // ill-formed, would create a dangling reference};

For v1 and v2, the initializer_list object
is a parameter in a function call, so the array created for{ 1, 2, 3 } has full-expression lifetime[.](#list-6.sentence-3)

For i3, the initializer_list object is a variable,
so the array persists for the lifetime of the variable[.](#list-6.sentence-4)

For i4, the initializer_list object is initialized in
the constructor's [*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]") as if by binding
a temporary array to a reference member, so the program is
ill-formed ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#list-6.sentence-5)

â *end example*]

[7](#list-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6758)

A [*narrowing conversion*](#def:conversion,narrowing "9.5.5 List-initialization [dcl.init.list]") is an implicit conversion

- [(7.1)](#list-7.1)

from a floating-point type to an integer type, or

- [(7.2)](#list-7.2)

from a floating-point type T to another floating-point type
whose floating-point conversion rank is neither greater than nor equal to
that of T,
except where the result of the conversion is a constant expression and
either its value is finite and the conversion did not overflow, or
the values before and after the conversion are not finite, or

- [(7.3)](#list-7.3)

from an integer type or unscoped enumeration type to a floating-point type, except
where the source is a constant expression and the actual value after conversion will fit
into the target type and will produce the original value when converted back to the
original type, or

- [(7.4)](#list-7.4)

from an integer type or unscoped enumeration type to an integer type that cannot
represent all the values of the original type, except where
  * [(7.4.1)](#list-7.4.1)

the source is a bit-field whose width w is less than that of its type
(or, for an enumeration type, its underlying type) and
the target type can represent all the values
of a hypothetical extended integer type
with width w and with the same signedness as the original type or

  * [(7.4.2)](#list-7.4.2)

the source is a constant
expression whose value after integral promotions will fit into the target type, or

- [(7.5)](#list-7.5)

from a pointer type or a pointer-to-member type to bool[.](#list-7.sentence-1)

[*Note [7](#list-note-7)*:

As indicated above, such conversions are not allowed at the top level in
list-initializations[.](#list-7.sentence-2)

â *end note*]

[*Example [14](#list-example-14)*: int x = 999; // x is not a constant expressionconst int y = 999;const int z = 99;char c1 = x; // OK, though it potentially narrows (in this case, it does narrow)char c2{x}; // error: potentially narrowschar c3{y}; // error: narrows (assuming char is 8 bits)char c4{z}; // OK, no narrowing neededunsigned char uc1 = {5}; // OK, no narrowing neededunsigned char uc2 = {-1}; // error: narrowsunsigned int ui1 = {-1}; // error: narrowssigned int si1 ={ (unsigned int)-1 }; // error: narrowsint ii = {2.0}; // error: narrowsfloat f1 { x }; // error: potentially narrowsfloat f2 { 7 }; // OK, 7 can be exactly represented as a floatbool b = {"meow"}; // error: narrowsint f(int);int a[] = { 2, f(2), f(2.0) }; // OK, the double-to-int conversion is not at the top level â *end example*]
