[intro.object] (original) (raw)
6 Basics [basic]
6.7 Memory and objects [basic.memobj]
6.7.2 Object model [intro.object]
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects.
An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).
[Note 1:
A function is not an object, regardless of whether or not it occupies storage in the way that objects do.
— _end note_]
The properties of an object are determined when the object is created.
[Note 2:
Some objects are polymorphic ([class.virtual]); the implementation generates information associated with each such object that makes it possible to determine that object's type during program execution.
— _end note_]
Objects can contain other objects, called subobjects.
An object that is not a subobject of any other object is called a complete object.
If an object is created in storage associated with a member subobject or array element e(which may or may not be within its lifetime), the created object is a subobject of e's containing object if
- the lifetime of e's containing object has begun and not ended, and
- the storage for the new object exactly overlays the storage location associated with e, and
- the new object is of the same type as e (ignoring cv-qualification).
If a complete object is created ([expr.new]) in storage associated with another object _e_of type “array of N unsigned char” or of type “array of N std::byte” ([cstddef.syn]), that array provides storagefor the created object if
- the lifetime of e has begun and not ended, and
- the storage for the new object fits entirely within e, and
- there is no array object that satisfies these constraints nested within e.
[Note 3:
If that portion of the array previously provided storage for another object, the lifetime of that object ends because its storage was reused ([basic.life]).
— _end note_]
[Example 1: template<typename ...T> struct AlignedUnion { alignas(T...) unsigned char data[max(sizeof(T)...)];};int f() { AlignedUnion<int, char> au;int *p = new (au.data) int; char *c = new (au.data) char(); char *d = new (au.data + 1) char();return *c + *d; } struct A { unsigned char a[32]; };struct B { unsigned char b[16]; };alignas(int) A a; B *b = new (a.a + 8) B; int *p = new (b->b + 4) int; — _end example_]
An object a is nested within another object b if
- a is a subobject of b, or
- b provides storage for a, or
- there exists an object _c_where a is nested within c, and c is nested within b.
For every object x, there is some object called thecomplete object of x, determined as follows:
- If x is a complete object, then the complete object of x is itself.
- Otherwise, the complete object of x is the complete object of the (unique) object that contains x.
If a complete object, a member subobject, or an array element is of class type, its type is considered the most derived class, to distinguish it from the class type of any base class subobject; an object of a most derived class type or of a non-class type is called amost derived object.
A potentially-overlapping subobject is either:
- a base class subobject, or
- a non-static data member declared with the no_unique_address attribute.
An object has nonzero size if it
- is not a potentially-overlapping subobject, or
- is not of class type, or
- is of a class type with virtual member functions or virtual base classes, or
- has subobjects of nonzero size or unnamed bit-fields of nonzero length.
Otherwise, if the object is a base class subobject of a standard-layout class type with no non-static data members, it has zero size.
Otherwise, the circumstances under which the object has zero size are implementation-defined.
Unless it is a bit-field, an object with nonzero size shall occupy one or more bytes of storage, including every byte that is occupied in full or in part by any of its subobjects.
An object of trivially copyable or standard-layout type ([basic.types.general]) shall occupy contiguous bytes of storage.
An object is a potentially non-unique object if it is a string literal object ([lex.string]), the backing array of an initializer list ([dcl.init.ref]), or a subobject thereof.
Unless an object is a bit-field or a subobject of zero size, the address of that object is the address of the first byte it occupies.
Two objects with overlapping lifetimes that are not bit-fields may have the same address if
- one is nested within the other,
- at least one is a subobject of zero size and they are not of similar types ([conv.qual]), or
- they are both potentially non-unique objects;
otherwise, they have distinct addresses and occupy disjoint bytes of storage.20
[Example 2: static const char test1 = 'x';static const char test2 = 'x';const bool b = &test1 != &test2; static const char (&r) [] = "x";static const char *s = "x";static std::initializer_list<char> il = { 'x' };const bool b2 = r != il.begin(); const bool b3 = r != s; const bool b4 = il.begin() != &test1; const bool b5 = r != &test1; — _end example_]
The address of a non-bit-field subobject of zero size is the address of an unspecified byte of storage occupied by the complete object of that subobject.
Some operations are described asimplicitly creating objectswithin a specified region of storage.
For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types ([basic.types.general]) in its specified region of storage if doing so would result in the program having defined behavior.
If no such set of objects would give the program defined behavior, the behavior of the program is undefined.
If multiple such sets of objects would give the program defined behavior, it is unspecified which such set of objects is created.
[Note 4:
Such operations do not start the lifetimes of subobjects of such objects that are not themselves of implicit-lifetime types.
— _end note_]
Further, after implicitly creating objects within a specified region of storage, some operations are described as producing a pointer to asuitable created object.
These operations select one of the implicitly-created objects whose address is the address of the start of the region of storage, and produce a pointer value that points to that object, if that value would result in the program having defined behavior.
If no such pointer value would give the program defined behavior, the behavior of the program is undefined.
If multiple such pointer values would give the program defined behavior, it is unspecified which such pointer value is produced.
[Example 3: #include <cstdlib> struct X { int a, b; }; X *make_x() { X *p = (X*)std::malloc(sizeof(struct X)); p->a = 1; p->b = 2;return p;} — _end example_]
Except during constant evaluation, an operation that begins the lifetime of an array of unsigned char or std::byteimplicitly creates objects within the region of storage occupied by the array.
[Note 5:
The array object provides storage for these objects.
— _end note_]
Except during constant evaluation, any implicit or explicit invocation of a function named operator new or operator new[]implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object.