[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(i2); // binds directly to i2 B&& rrb = x; // binds directly to the result of operator Bconstexpr int f() {const int &x = 42; const_cast(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 z{1,2};new std::vector{"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 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 or reference tocv std​::​initializer_list 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 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 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); // #1 S(std::initializer_list); // #2 S(std::initializer_list); // #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>);}; 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); // #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);}; B b1 { 1, 2 }; // creates initializer_list 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 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 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 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);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(__a, __a+3));}void h() {static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array f(std::initializer_list(__b, __b+3));}void r() {const A __c[3] = {A{1}, A{2}, A{3}}; // backing array q(std::initializer_list(__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 cmplx; std::vector v1 = { 1, 2, 3 }; void f() { std::vector v2{ 1, 2, 3 }; std::initializer_list i3 = { 1, 2, 3 };}struct A { std::initializer_list 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*]