[class.cdtor] (original) (raw)

11 Classes [class]

11.9 Initialization [class.init]

11.9.5 Construction and destruction [class.cdtor]

For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior.

For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor finishes execution results in undefined behavior.

[Example 1: struct X { int i; };struct Y : X { Y(); }; struct A { int a; };struct B : public A { int j; Y y; }; extern B bobj; B* pb = &bobj; int* p1 = &bobj.a; int* p2 = &bobj.y.i; A* pa = &bobj; B bobj; extern X xobj;int* p3 = &xobj.i; X xobj;

For another example,struct W { int j; };struct X : public virtual W { };struct Y { int* p; X x; Y() : p(&x.j) { } };

— _end example_]

During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor'sthispointer, the value of the object or subobject thus obtained is unspecified.

[Example 2: struct C;void no_opt(C*);struct C { int c; C() : c(0) { no_opt(this); } };const C cobj;void no_opt(C* cptr) { int i = cobj.c * 100; cptr->c = 1; cout << cobj.c * 100 << '\n';} extern struct D d;struct D { D(int a) : a(a), b(d.a) {} int a, b;}; D d = D(1); — _end example_]

To explicitly or implicitly convert a pointer (a glvalue) referring to an object of classXto a pointer (reference) to a direct or indirect base classBofX, the construction ofXand the construction of all of its direct or indirect bases that directly or indirectly derive fromBshall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior.

To form a pointer to (or access the value of) a direct non-static member of an objectobj, the construction ofobjshall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.

[Example 3: struct A { };struct B : virtual A { };struct C : B { };struct D : virtual A { D(A*); };struct X { X(A*); };struct E : C, D, X { E() : D(this), X(this) {} }; — _end example_]

Member functions, including virtual functions ([class.virtual]), can be called during construction or destruction ([class.base.init]).

When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class's non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor's or destructor's class and not one overriding it in a more-derived class.

If the virtual function call uses an explicit class member access ([expr.ref]) and the object expression refers to the complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

[Example 4: struct V { virtual void f();virtual void g();};struct A : virtual V { virtual void f();};struct B : virtual V { virtual void g(); B(V*, A*);};struct D : A, B { virtual void f();virtual void g(); D() : B((A*)this, this) { } }; B::B(V* v, A* a) { f(); g(); v->g(); a->f(); } — _end example_]

Whentypeidis used in a constructor (including themem-initializer or default member initializer ([class.mem]) for a non-static data member) or in a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if the operand oftypeidrefers to the object under construction or destruction,typeidyields thestd​::​type_infoobject representing the constructor or destructor's class.

If the operand oftypeidrefers to the object under construction or destruction and the static type of the operand is neither the constructor or destructor's class nor one of its bases, the behavior is undefined.

When adynamic_castis used in a constructor (including themem-initializer or default member initializer for a non-static data member) or in a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if the operand of thedynamic_castrefers to the object under construction or destruction, this object is considered to be a most derived object that has the type of the constructor or destructor's class.

If the operand of thedynamic_castrefers to the object under construction or destruction and the static type of the operand is not a pointer to or object of the constructor or destructor's own class or one of its bases, thedynamic_castresults in undefined behavior.

[Example 5: struct V { virtual void f();};struct A : virtual V { };struct B : virtual V { B(V*, A*);};struct D : A, B { D() : B((A*)this, this) { } }; B::B(V* v, A* a) { typeid(*this); typeid(*v); typeid(*a); dynamic_cast<B*>(v); dynamic_cast<B*>(a); } — _end example_]