Стандарт C++ 11 (1119564), страница 78
Текст из файла (страница 78)
For an object with a non-trivialdestructor, referring to any non-static member or base class of the object after the destructor finishesexecution results in undefined behavior. [ Example:structstructstructstructXYAB{:{:int i; };X { Y(); };int a; };public A { int j; Y y; };// non-trivial// non-trivialextern B bobj;B* pb = &bobj;int* p1 = &bobj.a;int* p2 = &bobj.y.i;// OK// undefined, refers to base class member// undefined, refers to member’s memberA* pa = &bobj;B bobj;// undefined, upcast to a base class type// definition of bobjextern X xobj;int* p3 = &xobj.i;X xobj;//OK, X is a trivial class§ 12.7© ISO/IEC 2011 – All rights reserved275ISO/IEC 14882:2011(E)2For another example,struct W { int j; };struct X : public virtual W { };struct Y {int *p;X x;Y() : p(&x.j) {// undefined, x is not yet constructed}};— end example ]3To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference)to a direct or indirect base class B of X, the construction of X and the construction of all of its direct orindirect bases that directly or indirectly derive from B shall have started and the destruction of these classesshall not have completed, otherwise the conversion results in undefined behavior.
To form a pointer to (oraccess the value of) a direct non-static member of an object obj, the construction of obj shall have startedand its destruction shall not have completed, otherwise the computation of the pointer value (or accessingthe member value) results in undefined behavior.
[ Example:structstructstructstructstructABCDX{:::{};virtual A { };B { };virtual A { D(A*); };X(A*); };struct E : C, D, X {E() : D(this),//////////////X(this) {////}};undefined: upcast from E* to A*might use path E* → D* → A*but D is not constructedD((C*)this), // defined:E* → C* defined because E() has startedand C* → A* defined becauseC fully constructeddefined: upon construction of X,C/B/D/A sublattice is fully constructed— end example ]4Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).When a virtual function is called directly or indirectly from a constructor or from a destructor, includingduring the construction or destruction of the class’s non-static data members, and the object to which thecall applies is the object (call it x) under construction or destruction, the function called is the final overriderin the constructor’s or destructor’s class and not one overriding it in a more-derived class.
If the virtualfunction call uses an explicit class member access (5.2.5) and the object expression refers to the completeobject of x or one of that object’s base class subobjects but not x or one of its base class subobjects, thebehavior is undefined. [ Example:struct V {virtual void f();virtual void g();};§ 12.7276© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)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();}////////calls V::f, not A::fcalls B::g, not D::gv is base of B, the call is well-defined, calls B::gundefined behavior, a’s type not a base of B— end example ]5The typeid operator (5.2.8) can be used during construction or destruction (12.6.2).
When typeid is usedin a constructor (including the mem-initializer or brace-or-equal-initializer for a non-static data member) orin a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if theoperand of typeid refers to the object under construction or destruction, typeid yields the std::type_infoobject representing the constructor or destructor’s class. If the operand of typeid refers to the object underconstruction or destruction and the static type of the operand is neither the constructor or destructor’s classnor one of its bases, the result of typeid is undefined.6dynamic_casts (5.2.7) can be used during construction or destruction (12.6.2). When a dynamic_castis used in a constructor (including the mem-initializer or brace-or-equal-initializer for a non-static datamember) or in a destructor, or used in a function called (directly or indirectly) from a constructor ordestructor, if the operand of the dynamic_cast refers to the object under construction or destruction, thisobject is considered to be a most derived object that has the type of the constructor or destructor’s class.
Ifthe operand of the dynamic_cast refers to the object under construction or destruction and the static typeof the operand is not a pointer to or object of the constructor or destructor’s own class or one of its bases,the dynamic_cast results in undefined behavior.[ Example: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) { }§ 12.7© ISO/IEC 2011 – All rights reserved277ISO/IEC 14882:2011(E)};B::B(V* v, A* a) {typeid(*this);typeid(*v);typeid(*a);dynamic_cast<B*>(v);dynamic_cast<B*>(a);////////////////type_info for Bwell-defined: *v has type V, a base of Byields type_info for Bundefined behavior: type A not a base of Bwell-defined: v of type V*, V base of Bresults in B*undefined behavior,a has type A*, A not a base of B}— end example ]12.8Copying and moving class objects[class.copy]1A class object can be copied or moved in two ways: by initialization (12.1, 8.5), including for function argument passing (5.2.2) and for function value return (6.6.3); and by assignment (5.17).
Conceptually, these twooperations are implemented by a copy/move constructor (12.1) and copy/move assignment operator (13.5.3).2A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,volatile X& or const volatile X&, and either there are no other parameters or else all other parametershave default arguments (8.3.6).
[ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.struct X {X(int);X(const X&, int = 1);};X a(1);// calls X(int);X b(a, 0);// calls X(const X&, int);X c = b;// calls X(const X&, int);— end example ]3A non-template constructor for class X is a move constructor if its first parameter is of type X&&, constX&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all otherparameters have default arguments (8.3.6).
[ Example: Y::Y(Y&&) is a move constructor.struct Y {Y(const Y&);Y(Y&&);};extern Y f(int);Y d(f(1));Y e = d;// calls Y(Y&&)// calls Y(const Y&)— end example ]4[ Note: All forms of copy/move constructor may be declared for a class. [ Example:struct X {X(const X&);X(X&);X(X&&);X(const X&&);};// OK// OK, but possibly not sensible§ 12.8278© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)— end example ] — end note ]5[ Note: If a class X only has a copy constructor with a parameter of type X&, an initializer of type const Xor volatile X cannot initialize an object of type (possibly cv-qualified) X. [ Example:struct X {X();X(X&);};const X cx;X x = cx;// default constructor// copy constructor with a nonconst parameter// error: X::X(X&) cannot copy cx into x— end example ] — end note ]6A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-qualified)X and either there are no other parameters or else all other parameters have default arguments.
A memberfunction template is never instantiated to produce such a constructor signature. [ Example:struct S {template<typename T> S(T);S();};S g;void h() {S a(g);// does not instantiate the member template to produce S::S<S>(S);// uses the implicitly declared copy constructor}— end example ]7If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the classdefinition declares a move constructor or move assignment operator, the implicitly declared copy constructoris defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class hasa user-declared copy assignment operator or a user-declared destructor.
Thus, for the class definitionstruct X {X(const X&, int);};a copy constructor is implicitly-declared. If the user-declared constructor is later defined asX::X(const X& x, int i =0) { /∗ ... ∗/ }then any use of X’s copy constructor is ill-formed because of the ambiguity; no diagnostic is required.8The implicitly-declared copy constructor for a class X will have the formX::X(const X&)if— each direct or virtual base class B of X has a copy constructor whose first parameter is of type constB& or const volatile B&, and§ 12.8© ISO/IEC 2011 – All rights reserved279ISO/IEC 14882:2011(E)— for all the non-static data members of X that are of a class type M (or array thereof), each such classtype has a copy constructor whose first parameter is of type const M& or const volatile M&.119Otherwise, the implicitly-declared copy constructor will have the formX::X(X&)9If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declaredas defaulted if and only if— X does not have a user-declared copy constructor,— X does not have a user-declared copy assignment operator,— X does not have a user-declared move assignment operator,— X does not have a user-declared destructor, and— the move constructor would not be implicitly defined as deleted.[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwisewould have invoked the move constructor may instead invoke a copy constructor.