Стандарт C++ 11 (1119564), страница 76
Текст из файла (страница 76)
The invocation of a destructor is subject to the usualrules for member functions (9.3), that is, if the object is not of the destructor’s class type and not of a classderived from the destructor’s class type, the program has undefined behavior (except that invoking deleteon a null pointer has no effect). [ Example:struct B {virtual ~B() { }};struct D : B {~D() { }};D D_object;typedef B B_alias;B* B_ptr = &D_object;void f() {§ 12.4266© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)D_object.B::~B();B_ptr->~B();B_ptr->~B_alias();B_ptr->B_alias::~B();B_ptr->B_alias::~B_alias();//////////callscallscallscallscallsB’sD’sD’sB’sB’sdestructordestructordestructordestructordestructor}— end example ] [ Note: An explicit destructor call must always be written using a member access operator (5.2.5) or a qualified-id (5.1); in particular, the unary-expression ˜X() in a member function is not anexplicit destructor call (5.3.1).
— end note ]14[ Note: explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specificaddresses using a new-expression with the placement option. Such use of explicit placement and destructionof objects can be necessary to cope with dedicated hardware resources and for writing memory managementfacilities. For example,void* operator new(std::size_t, void* p) { return p; }struct X {X(int);~X();};void f(X* p);void g() {// rare, specialized use:char* buf = new char[sizeof(X)];X* p = new(buf) X(222);// use buf[] and initializef(p);p->X::~X();// cleanup}— end note ]15Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if thedestructor is invoked for an object whose lifetime has ended (3.8).
[ Example: if the destructor for anautomatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarilyinvoke implicit destruction of the object, the behavior is undefined. — end example ]16[ Note: the notation for explicit call of a destructor can be used for any scalar type name (5.2.4). Allowingthis makes it possible to write code without having to know if a destructor exists for a given type.
Forexample,typedef int I;I* p;p->I::~I();— end note ]12.512Free store[class.free]Any allocation function for a class T is a static member (even if not explicitly declared static).[ Example:class Arena;struct B {void* operator new(std::size_t, Arena*);§ 12.5© ISO/IEC 2011 – All rights reserved267ISO/IEC 14882:2011(E)};struct D1 : B {};Arena* ap;void foo(int i) {new (ap) D1;new D1[i];new D1;}// calls B::operator new(std::size_t, Arena*)// calls ::operator new[](std::size_t)// ill-formed: ::operator new(std::size_t) hidden— end example ]3When an object is deleted with a delete-expression (5.3.5), a deallocation function (operator delete() fornon-array objects or operator delete[]() for arrays) is (implicitly) called to reclaim the storage occupiedby the object (3.7.4.2).4If a delete-expression begins with a unary :: operator, the deallocation function’s name is looked up inglobal scope.
Otherwise, if the delete-expression is used to deallocate a class object whose static type hasa virtual destructor, the deallocation function is the one selected at the point of definition of the dynamictype’s virtual destructor (12.4).117 Otherwise, if the delete-expression is used to deallocate an object ofclass T or array thereof, the static and dynamic types of the object shall be identical and the deallocationfunction’s name is looked up in the scope of T.
If this lookup fails to find the name, the name is looked up inthe global scope. If the result of the lookup is ambiguous or inaccessible, or if the lookup selects a placementdeallocation function, the program is ill-formed.5When a delete-expression is executed, the selected deallocation function shall be called with the address ofthe block of storage to be reclaimed as its first argument and (if the two-parameter style is used) the size ofthe block as its second argument.1186Any deallocation function for a class X is a static member (even if not explicitly declared static).
[ Example:class X {void operator delete(void*);void operator delete[](void*, std::size_t);};class Y {void operator delete(void*, std::size_t);void operator delete[](void*);};— end example ]7Since member allocation and deallocation functions are static they cannot be virtual. [ Note: however,when the cast-expression of a delete-expression refers to an object of class type, because the deallocationfunction actually called is looked up in the scope of the class that is the dynamic type of the object, if thedestructor is virtual, the effect is the same. For example,struct B {virtual ~B();void operator delete(void*, std::size_t);117) A similar provision is not needed for the array version of operator delete because 5.3.5 requires that in this situation,the static type of the object to be deleted be the same as its dynamic type.118) If the static type of the object to be deleted is different from the dynamic type and the destructor is not virtual the sizemight be incorrect, but that case is already undefined; see 5.3.5.§ 12.5268© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)};struct D : B {void operator delete(void*);};void f() {B* bp = new D;delete bp;}//1: uses D::operator delete(void*)Here, storage for the non-array object of class D is deallocated by D::operator delete(), due to thevirtual destructor.
— end note ] [ Note: Virtual destructors have no effect on the deallocation functionactually called when the cast-expression of a delete-expression refers to an array of objects of class type. Forexample,struct B {virtual ~B();void operator delete[](void*, std::size_t);};struct D : B {void operator delete[](void*, std::size_t);};void f(int i) {D* dp = new D[i];delete [] dp;// uses D::operator delete[](void*, std::size_t)B* bp = new D[i];delete[] bp;// undefined behavior}— end note ]8Access to the deallocation function is checked statically.
Hence, even though a different one might actuallybe executed, the statically visible deallocation function is required to be accessible. [ Example: for the callon line //1 above, if B::operator delete() had been private, the delete expression would have beenill-formed. — end example ]9[ Note: If a deallocation function has no explicit exception-specification, it is treated as if it were specifiedwith noexcept(true) (15.4). — end note ]12.6Initialization[class.init]1When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or theinitializer has the form (), the object is initialized as specified in 8.5.2An object of class type (or array thereof) can be explicitly initialized; see 12.6.1 and 12.6.2.3When an array of class objects is initialized (either explicitly or implicitly) and the elements are initializedby constructor, the constructor shall be called for each element of the array, following the subscript order;see 8.3.4.
[ Note: Destructors for the array elements are called in reverse order of their construction. — endnote ]12.6.11Explicit initialization[class.expl.init]An object of class type can be initialized with a parenthesized expression-list, where the expression-list§ 12.6.1© ISO/IEC 2011 – All rights reserved269ISO/IEC 14882:2011(E)is construed as an argument list for a constructor that is called to initialize the object. Alternatively, asingle assignment-expression can be specified as an initializer using the = form of initialization. Eitherdirect-initialization semantics or copy-initialization semantics apply; see 8.5.
[ Example:struct complex {complex();complex(double);complex(double,double);};complex sqrt(complex,complex);complex a(1);complex b = a;complex c = complex(1,2);complex d = sqrt(b,c);complex e;complex f = 3;complex g = { 1, 2 };////////////////////////////////initialize by a call ofcomplex(double)initialize by a copy of aconstruct complex(1,2)using complex(double,double)copy/move it into ccall sqrt(complex,complex)and copy/move the result into dinitialize by a call ofcomplex()construct complex(3) usingcomplex(double)copy/move it into fconstruct complex(1, 2)using complex(double, double)and copy/move it into g— end example ] [ Note: overloading of the assignment operator (13.5.3) has no effect on initialization.
— endnote ]2An object of class type can also be initialized by a braced-init-list. List-initialization semantics apply; see 8.5and 8.5.4. [ Example:complex v[6] = { 1, complex(1,2), complex(), 2 };Here, complex::complex(double) is called for the initialization of v[0] and v[3], complex::complex(double, double) is called for the initialization of v[1], complex::complex() is called for the initializationv[2], v[4], and v[5].