Стандарт C++ 98 (1119566), страница 16
Текст из файла (страница 16)
]4A program may end the lifetime of any object by reusing the storage which the object occupies or byexplicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of aclass type with a non-trivial destructor, the program is not required to call the destructor explicitly beforethe storage which the object occupies is reused or released; however, if there is no explicit call to thedestructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not beimplicitly called and any program that depends on the side effects produced by the destructor has undefined__________________33) On some implementations, it causes a system-generated runtime fault.48© ISO/IECISO/IEC 14882:1998(E)3 Basic concepts3.8 Object Lifetimebehavior.5Before the lifetime of an object has started but after the storage which the object will occupy has been allocated34) or, after the lifetime of an object has ended and before the storage which the object occupied isreused or released, any pointer that refers to the storage location where the object will be or was locatedmay be used but only in limited ways.
Such a pointer refers to allocated storage (3.7.3.2), and using thepointer as if the pointer were of type void*, is well-defined. Such a pointer may be dereferenced but theresulting lvalue may only be used in limited ways, as described below. If the object will be or was of aclass type with a non-trivial destructor, and the pointer is used as the operand of a delete-expression, theprogram has undefined behavior. If the object will be or was of a non-POD class type, the program hasundefined behavior if:— the pointer is used to access a non-static data member or call a non-static member function of the object,or— the pointer is implicitly converted (4.10) to a pointer to a base class type, or— the pointer is used as the operand of a static_cast (5.2.9) (except when the conversion is tovoid*, or to void* and subsequently to char*, or unsigned char*).— the pointer is used as the operand of a dynamic_cast (5.2.7). [Example:struct B {virtual void f();void mutate();virtual ~B();};struct D1 : B { void f(); };struct D2 : B { void f(); };void B::mutate() {new (this) D2;f();...
= this;}// reuses storage – ends the lifetime of *this// undefined behavior// OK, this points to valid memoryvoid g() {void* p = malloc(sizeof(D1) + sizeof(D2));B* pb = new (p) D1;pb->mutate();&pb;// OK: pb points to valid memoryvoid* q = pb;// OK: pb points to valid memorypb->f();// undefined behavior, lifetime of *pb has ended}—end example]6Similarly, before the lifetime of an object has started but after the storage which the object will occupy hasbeen allocated or, after the lifetime of an object has ended and before the storage which the object occupiedis reused or released, any lvalue which refers to the original object may be used but only in limited ways.Such an lvalue refers to allocated storage (3.7.3.2), and using the properties of the lvalue which do notdepend on its value is well-defined.
If an lvalue-to-rvalue conversion (4.1) is applied to such an lvalue, theprogram has undefined behavior; if the original object will be or was of a non-POD class type, the programhas undefined behavior if:— the lvalue is used to access a non-static data member or call a non-static member function of the object,or__________________34) For example, before the construction of a global object of non-POD class type (12.7).49ISO/IEC 14882:1998(E)© ISO/IEC3.8 Object Lifetime3 Basic concepts— the lvalue is implicitly converted (4.10) to a reference to a base class type, or— the lvalue is used as the operand of a static_cast (5.2.9) (except when the conversion is ultimatelyto char& or unsigned char&), or— the lvalue is used as the operand of a dynamic_cast (5.2.7) or as the operand of typeid.7If, after the lifetime of an object has ended and before the storage which the object occupied is reused orreleased, a new object is created at the storage location which the original object occupied, a pointer thatpointed to the original object, a reference that referred to the original object, or the name of the originalobject will automatically refer to the new object and, once the lifetime of the new object has started, can beused to manipulate the new object, if:— the storage for the new object exactly overlays the storage location which the original object occupied,and— the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and— the original object was a most derived object (1.8) of type T and the new object is a most derived objectof type T (that is, they are not base class subobjects).
[Example:struct C {int i;void f();const C& operator=( const C& );};const C& C::operator=( const C& other){if ( this != &other ) {this->~C();new (this) C(other);f();}return *this;}C c1;C c2;c1 = c2;c1.f();// lifetime of *this ends// new object of type C created// well-defined// well-defined// well-defined; c1 refers to a new object of type C—end example]8If a program ends the lifetime of an object of type T with static (3.7.1) or automatic (3.7.2) storage durationand if T has a non-trivial destructor,35) the program must ensure that an object of the original type occupiesthat same storage location when the implicit destructor call takes place; otherwise the behavior of the program is undefined. This is true even if the block is exited with an exception.
[Example:class T { };struct B {~B();};void h() {B b;new (&b) T;}// undefined behavior at block exit—end example]__________________35) that is, an object for which a destructor will be called implicitly—either either upon exit from the block for an object with automatic storage duration or upon exit from the program for an object with static storage duration.50© ISO/IECISO/IEC 14882:1998(E)3 Basic concepts93.8 Object LifetimeCreating a new object at the storage location that a const object with static or automatic storage durationoccupies or, at the storage location that such a const object used to occupy before its lifetime endedresults in undefined behavior. [Example:struct B {B();~B();};const B b;void h() {b.~B();new (&b) const B;}// undefined behavior—end example]3.9 Types[basic.types]1[Note: 3.9 and the subclauses thereof impose requirements on implementations regarding the representationof types.
There are two kinds of types: fundamental types and compound types. Types describe objects(1.8), references (8.3.2), or functions (8.3.5). ]2For any complete POD object type T, whether or not the object holds a valid value of type T, the underlyingbytes (1.7) making up the object can be copied into an array of char or unsigned char.36) If the content of the array of char or unsigned char is copied back into the object, the object shall subsequentlyhold its original value. [Example:#define N sizeof(T)char buf[N];T obj;memcpy(buf, &obj, N);memcpy(&obj, buf, N);// obj initialized to its original value// between these two calls to memcpy,// obj might be modified// at this point, each subobject of obj of scalar type// holds its original value—end example]3For any POD type T, if two pointers to T point to distinct T objects obj1 and obj2, if the value of obj1is copied into obj2, using the memcpy library function, obj2 shall subsequently hold the same value asobj1.
[Example:T* t1p;T* t2p;memcpy(t1p, t2p, sizeof(T));// provided that t2p points to an initialized object ...// at this point, every subobject of POD type in *t1p contains// the same value as the corresponding subobject in *t2p—end example]4The object representation of an object of type T is the sequence of N unsigned char objects taken up bythe object of type T, where N equals sizeof(T). The value representation of an object is the set of bitsthat hold the value of type T. For POD types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.37)5Object types have alignment requirements (3.9.1, 3.9.2).
The alignment of a complete object type is animplementation-defined integer value representing a number of bytes; an object is allocated at an addressthat meets the alignment requirements of its object type.__________________36) By using, for example, the library functions (17.4.1.2) memcpy or memmove.37) The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.51ISO/IEC 14882:1998(E)© ISO/IEC3.9 Types3 Basic concepts6A class that has been declared but not defined, or an array of unknown size or of incomplete element type,is an incompletely-defined object type.38) Incompletely-defined object types and the void types are incomplete types (3.9.1). Objects shall not be defined to have an incomplete type.7A class type (such as “class X”) might be incomplete at one point in a translation unit and complete lateron; the type “class X” is the same type at both points.