[class.base.init] (original) (raw)
11 Classes [class]
11.10 Initialization [class.init]
11.10.2 Initializing bases and members [class.base.init]
In a mem-initializer-id an initial unqualifiedidentifier is looked up in the scope of the constructor's class and, if not found in that scope, it is looked up in the scope containing the constructor's definition.
[ Note
:
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 may 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
:
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 inherited virtual base class, themem-initializeris ill-formed.
[ Example
:
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
:
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
:
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
:
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
:
struct A {
A() : v(42) { }
const int& v;
};
— end example
]
In a non-delegating constructor, 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
- if the entity is a non-static data member that has a default member initializer ([class.mem]) and either
- the constructor's class is a union ([class.union]), and no other variant member of that union is designated by a mem-initializer-id or
- the constructor's class is not a union, and, if the entity is a member of an anonymous union, no other member of that union is designated by amem-initializer-id,
the entity is initialized from its default member initializer as specified in [dcl.init];
- otherwise, if the entity is an anonymous union or a variant member ([class.union.anon]), no initialization is performed;
- otherwise, the entity is default-initialized ([dcl.init]).
[ Note
:
An abstract class ([class.abstract]) is never a most derived class, thus its constructors never initialize virtual base classes, therefore the corresponding mem-initializers may be omitted.
— end note
]
An attempt to initialize more than one non-static data member of a union renders the program ill-formed.
[ Note
:
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 value.
— end note
]
[ Example
:
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
:
Given
struct 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
:
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
:
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:
- First, and only for the constructor of the most derived class ([intro.object]), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived classbase-specifier-list.
- Then, direct base classes are initialized in declaration order as they appear in thebase-specifier-list(regardless of the order of themem-initializers).
- Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of themem-initializers).
- Finally, the compound-statement of the constructor body is executed.
[ Note
:
The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization.
— end note
]
[ Example
:
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
]
[ Example
:
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
]
[ Note
:
Because themem-initializerare evaluated in the scope of the constructor, thethispointer can be used in theexpression-listof amem-initializerto refer to the object being initialized.
— end note
]
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-initializersfor base classes have completed, the program has undefined behavior.
[ Example
:
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
:
[class.cdtor] describes the result 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
:
template<class... Mixins> class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } };
— end example
]