[class.base.init] (original) (raw)

11 Classes [class]

11.9 Initialization [class.init]

11.9.3 Initializing bases and members [class.base.init]

In the definition of a constructor for a class, initializers for direct and virtual base class subobjects and non-static data members can be specified by actor-initializer, which has the form

Lookup for an unqualified name in a mem-initializer-idignores the constructor's function parameter scope.

[Note 1:

If the constructor's class contains a member with the same name as a direct or virtual base class of the class, amem-initializer-idnaming the member or base class and composed of a single identifier refers to the class member.

Amem-initializer-idfor the hidden base class can be specified using a qualified name.

— _end note_]

Unless themem-initializer-idnames the constructor's class, a non-static data member of the constructor's class, or a direct or virtual base of that class, themem-initializeris ill-formed.

Amem-initializer-listcan initialize a base class using any class-or-decltype that denotes that base class type.

[Example 1: struct A { A(); };typedef A global_A;struct B { };struct C: public A, public B { C(); }; C::C(): global_A() { } — _end example_]

If amem-initializer-idis ambiguous because it designates both a direct non-virtual base class and an indirect virtual base class, themem-initializeris ill-formed.

[Example 2: struct A { A(); };struct B: public virtual A { };struct C: public A, public B { C(); }; C::C(): A() { } — _end example_]

Actor-initializermay initialize a variant member of the constructor's class.

If actor-initializerspecifies more than onemem-initializerfor the same member or for the same base class, thector-initializeris ill-formed.

A mem-initializer-list can delegate to another constructor of the constructor's class using anyclass-or-decltype that denotes the constructor's class itself.

If amem-initializer-id designates the constructor's class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by themem-initializer is the target constructor.

The target constructor is selected by overload resolution.

Once the target constructor returns, the body of the delegating constructor is executed.

If a constructor delegates to itself directly or indirectly, the program is ill-formed, no diagnostic required.

[Example 3: struct C { C( int ) { } C(): C(42) { } C( char c ) : C(42.0) { } C( double d ) : C('a') { } }; — _end example_]

Theexpression-listor braced-init-listin amem-initializeris used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.

[Example 4: struct B1 { B1(int); };struct B2 { B2(int); };struct D : B1, B2 { D(int); B1 b;const int c;}; D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { }D d(10); — _end example_]

[Note 2:

The initialization performed by each mem-initializerconstitutes a full-expression ([intro.execution]).

Any expression in amem-initializeris evaluated as part of the full-expression that performs the initialization.

— _end note_]

A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.

A temporary expression bound to a reference member in a mem-initializeris ill-formed.

[Example 5: struct A { A() : v(42) { } const int& v;}; — _end example_]

In a non-delegating constructor other than an implicitly-defined copy/move constructor ([class.copy.ctor]), if a given potentially constructed subobject is not designated by amem-initializer-id(including the case where there is nomem-initializer-listbecause the constructor has noctor-initializer), then

[Note 3:

An abstract class ([class.abstract]) is never a most derived class, thus its constructors never initialize virtual base classes, therefore the corresponding mem-initializers can be omitted.

— _end note_]

An attempt to initialize more than one non-static data member of a union renders the program ill-formed.

[Note 4:

After the call to a constructor for classXfor an object with automatic or dynamic storage duration has completed, if the constructor was not invoked as part of value-initialization and a member ofXis neither initialized nor given a value during execution of the compound-statement of the body of the constructor, the member has an indeterminate or erroneous value ([basic.indet]).

— _end note_]

[Example 6: struct A { A();};struct B { B(int);};struct C { C() { } A a; const B b; int i; int j = 5; }; — _end example_]

If a given non-static data member has both a default member initializer and a mem-initializer, the initialization specified by themem-initializer is performed, and the non-static data member's default member initializer is ignored.

[Example 7:

Givenstruct A { int i = ; A(int arg) : i(arg) { } };the A(int) constructor will simply initialize i to the value ofarg, and theside effects in i's default member initializer will not take place.

— _end example_]

A temporary expression bound to a reference member from a default member initializer is ill-formed.

[Example 8: struct A { A() = default; A(int v) : v(v) { } const int& v = 42; }; A a1; A a2(1); — _end example_]

In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked ([class.dtor]).

[Note 5:

This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([except.ctor]).

— _end note_]

In a non-delegating constructor, initialization proceeds in the following order:

[Note 6:

The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization.

— _end note_]

[Example 9: struct V { V(); V(int);};struct A : virtual V { A(); A(int);};struct B : virtual V { B(); B(int);};struct C : A, B, virtual V { C(); C(int);}; A::A(int i) : V(i) { }B::B(int i) { }C::C(int i) { }V v(1); A a(2); B b(3); C c(4); — _end example_]

[Note 7:

The expression-list or braced-init-listof a mem-initializeris in the function parameter scope of the constructor and can use this to refer to the object being initialized.

— _end note_]

[Example 10: class X { int a;int b;int i;int j;public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) { } };

initializesX​::​rto refer toX​::​a, initializesX​::​bwith the value of the constructor parameteri, initializesX​::​iwith the value of the constructor parameteri, and initializesX​::​jwith the value ofX​::​i; this takes place each time an object of classXis created.

— _end example_]

Member functions (including virtual member functions, [class.virtual]) can be called for an object under construction.

Similarly, an object under construction can be the operand of thetypeidoperator ([expr.typeid]) or of adynamic_cast ([expr.dynamic.cast]).

However, if these operations are performed in actor-initializer(or in a function called directly or indirectly from actor-initializer) before all themem-initializer_s_for base classes have completed, the program has undefined behavior.

[Example 11: class A { public: A(int);};class B : public A { int j;public: int f(); B() : A(f()), j(f()) { } };class C { public: C(int);};class D : public B, C { int i;public: D() : C(f()), i(f()) { } }; — _end example_]

[Note 8:

[class.cdtor] describes the results of virtual function calls,typeidanddynamic_casts during construction for the well-defined cases; that is, describes the polymorphic behavior of an object under construction.

— _end note_]

A mem-initializer followed by an ellipsis is a pack expansion ([temp.variadic]) that initializes the base classes specified by a pack expansion in the base-specifier-listfor the class.

[Example 12: template<class... Mixins> class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } }; — _end example_]