27 KiB
[dcl.init.general]
9 Declarations [dcl]
9.5 Initializers [dcl.init]
9.5.1 General [dcl.init.general]
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]), the initialization of a return value ([stmt.return]), or when an initializer follows a declarator.
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
braced-init-list:
{ initializer-list ,opt }
{ designated-initializer-list ,opt }
{ }
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...opt
designated-initializer-list:
designated-initializer-clause
designated-initializer-list , designated-initializer-clause
designated-initializer-clause:
designator brace-or-equal-initializer
expr-or-braced-init-list:
expression
braced-init-list
[Note 1:
The rules in [dcl.init] apply even if the grammar permits only the brace-or-equal-initializer form of initializer in a given context.
â end note]
Except for objects declared with the constexpr specifier, for which see [dcl.constexpr], an initializer 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.
[Example 1: int f(int);int a = 2;int b = f(a);int c(b); â end example]
[Note 2:
Default arguments are more restricted; see [dcl.fct.default].
â end note]
[Note 3:
The order of initialization of variables with static storage duration is described in [basic.start] and [stmt.dcl].
â end note]
A declaration D of a variable with linkage shall not have an initializer if D inhabits a block scope.
To zero-initialize an object or reference of type T means:
if T is std::meta::info, the object is initialized to a null reflection value;
if T is any other scalar type ([basic.types.general]), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;78
ifT is a (possibly cv-qualified) non-union class type, its padding bits ([basic.types.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;
ifT is a (possibly cv-qualified) union type, its padding bits ([basic.types.general]) are initialized to zero bits and the object's first non-static named data member is zero-initialized;
ifT is an array type, each element is zero-initialized;
ifT is a reference type, no initialization is performed.
Todefault-initialize an object of typeT means:
-
IfT is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one for theinitializer () is chosen through overload resolution ([over.match]). The constructor thus selected is called, with an empty argument list, to initialize the object.
-
IfT is an array type, the semantic constraints of default-initializing a hypothetical element shall be met and each element is default-initialized.
-
If T is std::meta::info, the object is zero-initialized.
-
Otherwise, no initialization is performed.
A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if
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,
if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,
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
each potentially constructed base class of T is const-default-constructible.
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.
Tovalue-initialize an object of typeT means:
-
IfT is a (possibly cv-qualified) class type ([class]), then let C be the constructor selected to default-initialize the object, if any. If C is not user-provided, the object is first zero-initialized. In all cases, the object is then default-initialized.
-
IfT is an array type, the semantic constraints of value-initializing a hypothetical element shall be met and each element is value-initialized.
-
Otherwise, the object is zero-initialized.
A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed.
[Note 4:
For every object with static storage duration, static initialization ([basic.start.static]) is performed at program startup before any other initialization takes place.
In some cases, additional initialization is done later.
â end note]
If no initializer is specified for an object, the object is default-initialized.
If the entity being initialized does not have class or array type, theexpression-list in a parenthesized initializer shall be a single expression.
The initialization that occurs in the = form of abrace-or-equal-initializer orcondition ([stmt.select]), as well as in argument passing, function return, throwing an exception ([except.throw]), handling an exception ([except.handle]), and aggregate member initialization other than by adesignated-initializer-clause ([dcl.init.aggr]), is calledcopy-initialization.
[Note 5:
Copy-initialization can invoke a move ([class.copy.ctor]).
â end note]
The initialization that occurs
for an initializer that is a parenthesized expression-list or a braced-init-list,
for a new-initializer ([expr.new]),
in a static_cast expression ([expr.static.cast]),
in a functional notation type conversion ([expr.type.conv]), and
in the braced-init-list form of a condition
is calleddirect-initialization.
The semantics of initializers are as follows.
Thedestination type is the cv-unqualified type of the object or reference being initialized and thesource type is the type of the initializer expression.
If the initializer is not a single (possibly parenthesized) expression, the source type is not defined.
-
If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized ([dcl.init.list]).
-
If the destination type is a reference type, see [dcl.init.ref].
-
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, see [dcl.init.string].
-
If the initializer is (), the object is value-initialized. [Note 6: Since() is not permitted by the syntax forinitializer,X a(); is not the declaration of an object of classX, but the declaration of a function taking no arguments and returning anX. The form() can appear in certain other initialization contexts ([expr.new], [expr.type.conv], [class.base.init]). â end note]
-
Otherwise, if the destination type is an array, the object is initialized as follows. The initializer shall be of the form( expression-list ). Let x1, …, xk be the elements of the expression-list. If the destination type is an array of unknown bound, it is defined as having k elements. Let n denote the array size after this potential adjustment. If k is greater than n, the program is ill-formed. Otherwise, the ith array element is copy-initialized withxi for each 1 ⤠i ⤠k, and value-initialized for each k<iâ¤n. 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.
-
Otherwise, if the destination type is a class type:
-
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. [Example 2: T x = T(T(T())); value-initializes x. â end example]
-
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. The applicable constructors are enumerated ([over.match.ctor]), and the best one is chosen through overload resolution ([over.match]). Then: + (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 as its argument(s).
-
[(16.6.2.2)](#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, the object is initialized as follows. Let e1, …, en be the elements of the aggregate ([dcl.init.aggr]). Let x1, …, xk be the elements of the expression-list. If k is greater than n, the program is ill-formed. The element ei is copy-initialized withxi for 1 ⤠i ⤠k. The remaining elements are initialized with their default member initializers, if any, and otherwise are value-initialized. 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. [Note 7: By contrast with direct-list-initialization, narrowing conversions ([dcl.init.list]) can appear, designators are not permitted, a temporary object bound to a reference does not have its lifetime extended ([class.temporary]), and there is no brace elision. [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)](#16.6.2.3)
Otherwise, the initialization is ill-formed[.](#16.6.2.3.sentence-1)
-
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], and the best one is chosen through overload resolution ([over.match]). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. 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. The call is used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
-
Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated ([over.match.conv]), and the best one is chosen through overload resolution ([over.match]). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
-
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.
-
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. A standard conversion sequence ([conv]) is used to convert the initializer expression to a prvalue of the destination type; no user-defined conversions are considered. If the conversion cannot be done, the initialization is ill-formed. When initializing a bit-field with a value that it cannot represent, the resulting value of the bit-field isimplementation-defined. [Note 8: An expression of type âcv1 Tâ can initialize an object of type âcv2 Tâ independently of the cv-qualifierscv1 and cv2. int a;const int b = a;int c = b; â end note]
An immediate invocation ([expr.const]) that is not evaluated where it appears ([dcl.fct.default], [class.mem.general]) is evaluated and checked for whether it is a constant expression at the point where the enclosing initializer is used in a function call, a constructor definition, or an aggregate initialization.
An initializer-clause followed by an ellipsis is a pack expansion ([temp.variadic]).
Initialization includes the evaluation of all subexpressions of each initializer-clause of the initializer (possibly nested within braced-init-lists) and the creation of any temporary objects for function arguments or return values ([class.temporary]).
If the initializer is a parenthesized expression-list, the expressions are evaluated in the order specified for function calls ([expr.call]).
The same identifier shall not appear in multiple designators of adesignated-initializer-list.
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.
[Note 9:
Such an object might have been value-initialized or initialized by aggregate initialization ([dcl.init.aggr]) or by an inherited constructor ([class.inhctor.init]).
â end note]
Destroying an object of class type invokes the destructor of the class.
Destroying a scalar type has no effect other than ending the lifetime of the object ([basic.life]).
Destroying an array destroys each element in reverse subscript order.
A declaration that specifies the initialization of a variable, whether from an explicit initializer or by default-initialization, is called the initializing declaration of that variable.
[Note 10:
In most cases this is the defining declaration ([basic.def]) of the variable, but the initializing declaration of a non-inline static data member ([class.static.data]) can be the declaration within the class definition and not the definition (if any) outside it.
â end note]
As specified in [conv.ptr], converting an integer literal whose value is0 to a pointer type results in a null pointer value.