Стандарт C++ 98 (1119566), страница 55
Текст из файла (страница 55)
The invocation of a destructor is subject to the usual rules for member functions(9.3), that is, if the object is not of the destructor’s class type and not of a class derived from thedestructor’s class type, the program has undefined behavior (except that invoking delete on a null pointerhas no effect).
[Example:struct B {virtual ~B() { }};struct D : B {~D() { }};192© ISO/IECISO/IEC 14882:1998(E)12 Special member functions12.4 DestructorsD D_object;typedef B B_alias;B* B_ptr = &D_object;void f() {D_object.B::~B();B_ptr->~B();B_ptr->~B_alias();B_ptr->B_alias::~B();B_ptr->B_alias::~B_alias();}// calls B’s destructor// calls D’s destructor// calls D’s destructor// calls B’s destructor// error, no B_alias in class B—end example] [Note: an explicit destructor call must always be written using a member access operator(5.2.5); in particular, the unary-expression ~X() in a member function is not an explicit destructor call(5.3.1). ]13[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 anddestruction of objects can be necessary to cope with dedicated hardware resources and for writing memorymanagement facilities. For example,void* operator new(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]14Once 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 an automatic 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. ]15[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]193ISO/IEC 14882:1998(E)© ISO/IEC12.4 Destructors12 Special member functions12.5 Free store[class.free]1Any allocation function for a class T is a static member (even if not explicitly declared static).2[Example:class Arena;struct B {void* operator new(size_t, Arena*);};struct D1 : B {};Arena* ap;void foo(int i){new (ap) D1;new D1[i];new D1;}// calls B::operator new(size_t, Arena*)// calls ::operator new[](size_t)// ill-formed: ::operator new(size_t) hidden—end example]3When an object is deleted with a delete-expression (5.3.5), a deallocation function(operator delete() for non-array objects or operator delete[]() for arrays) is (implicitly)called to reclaim the storage occupied by the object (3.7.3.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 has avirtual destructor, the deallocation function is the one found by the lookup in the definition of the dynamictype’s virtual destructor (12.4).104) 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 upin the global scope. If the result of the lookup is ambiguous or inaccessible, or if the lookup selects a placement deallocation 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.105)6Any 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*, size_t);};class Y {// ...void operator delete(void*, size_t);void operator delete[](void*);};—end example]__________________104) A similar lookup is not needed for the array version of operator delete because 5.3.5 requires that in this situation, the statictype of the delete-expression’s operand be the same as its dynamic type.105) If the static type in the delete-expression is different from the dynamic type and the destructor is not virtual the size might beincorrect, but that case is already undefined; see 5.3.5.194© ISO/IECISO/IEC 14882:1998(E)12 Special member functions712.5 Free storeSince 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*, size_t);};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.
] [Note: virtual destructors have no effect on the deallocation function actually calledwhen the cast-expression of a delete-expression refers to an array of objects of class type. For example,struct B {virtual ~B();void operator delete[](void*, size_t);};struct D : B {void operator delete[](void*, size_t);};void f(int i){D* dp = new D[i];delete [] dp;B* bp = new D[i];delete[] bp;}// uses D::operator delete[](void*, size_t)// 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 havebeen ill-formed. ]12.6 Initialization[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. [Note: if the class is a non-POD, it isdefault-initialized. ]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), the constructor shall be calledfor 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. ]195ISO/IEC 14882:1998(E)© ISO/IEC12.6.1 Explicit initialization12 Special member functions12.6.1 Explicit initialization1[class.expl.init]An object of class type can be initialized with a parenthesized expression-list, where the expression-list isconstrued as an argument list for a constructor that is called to initialize the object.
Alternatively, a singleassignment-expression can be specified as an initializer using the = form of initialization. Either directinitialization semantics or copy-initialization semantics apply; see 8.5. [Example:class complex {// ...public: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 of// complex(double)// initialize by a copy of a// construct complex(1,2)// using complex(double,double)// copy it into c// call sqrt(complex,complex)// and copy the result into d// initialize by a call of// complex()// construct complex(3) using// complex(double)// copy it into f// error; constructor is required—end example] [Note: overloading of the assignment operator (13.5.3) has no effect on initialization.
]2When an aggregate (whether class or array) contains members of class type and is initialized by a braceenclosed initializer-list (8.5.1), each such member is copy-initialized (see 8.5) by the correspondingassignment-expression. If there are fewer initializers in the initializer-list than members of the aggregate,each member not explicitly initialized shall be default-initialized (8.5). [Note: 8.5.1 describes howassignment-expressions in an initializer-list are paired with the aggregate members they initialize.
] [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)iscalledfortheinitializationofv[1],complex::complex() is called for the initialization v[2], v[4], and v[5]. For another example,class X {public:int i;float f;complex c;} x = { 99, 88.8, 77.7 };Here, x.i is initialized with 99, x.f is initialized with 88.8, and complex::complex(double) iscalled for the initialization of x.c.