[intro.object] # 6 Basics [[basic]](./#basic) ## 6.8 Memory and objects [[basic.memobj]](basic.memobj#intro.object) ### 6.8.2 Object model [intro.object] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3427) The constructs in a C++ program create, destroy, refer to, access, and manipulate objects[.](#1.sentence-1) An [*object*](#def:object "6.8.2 Object model [intro.object]") is created by a [definition](basic.def "6.2 Declarations and definitions [basic.def]"), by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a [union](class.union "11.5 Unions [class.union]"), or when a temporary object is created ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#1.sentence-2) An object occupies a region of storage in its period of construction ([[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")), throughout its [lifetime](basic.life "6.8.4 Lifetime [basic.life]"), and in its period of destruction ([[class.cdtor]](class.cdtor "11.9.5 Construction and destruction"))[.](#1.sentence-3) [*Note [1](#note-1)*: A function is not an object, regardless of whether or not it occupies storage in the way that objects do[.](#1.sentence-4) — *end note*] The properties of an object are determined when the object is created[.](#1.sentence-5) An object can have a name ([[basic.pre]](basic.pre "6.1 Preamble"))[.](#1.sentence-6) An object has a storage duration ([[basic.stc]](basic.stc "6.8.6 Storage duration")) which influences its lifetime ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#1.sentence-7) An object has a type ([[basic.types]](basic.types "6.9 Types"))[.](#1.sentence-8) [*Note [2](#note-2)*: Some objects are polymorphic ([[class.virtual]](class.virtual "11.7.3 Virtual functions")); the implementation generates information associated with each such object that makes it possible to determine that object's type during program execution[.](#1.sentence-9) — *end note*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3460) Objects can contain other objects, called [*subobjects*](#def:subobject "6.8.2 Object model [intro.object]")[.](#2.sentence-1) A subobject can be a [*member subobject*](#def:member_subobject "6.8.2 Object model [intro.object]") ([[class.mem]](class.mem "11.4 Class members")), a [*base class subobject*](#def:base_class_subobject "6.8.2 Object model [intro.object]") ([[class.derived]](class.derived "11.7 Derived classes")), or an array element[.](#2.sentence-2) An object that is not a subobject of any other object is called a [*complete object*](#def:complete_object "6.8.2 Object model [intro.object]")[.](#2.sentence-3) 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 - [(2.1)](#2.1) the lifetime of *e*'s containing object has begun and not ended, and - [(2.2)](#2.2) the storage for the new object exactly overlays the storage location associated with *e*, and - [(2.3)](#2.3) the new object is of the same type as *e* (ignoring cv-qualification)[.](#2.sentence-4) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3483) If a complete object is created ([[expr.new]](expr.new "7.6.2.8 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]](cstddef.syn "17.2.1 Header synopsis")), that array [*provides storage*](#def:provides_storage "6.8.2 Object model [intro.object]") for the created object if - [(3.1)](#3.1) the lifetime of *e* has begun and not ended, and - [(3.2)](#3.2) the storage for the new object fits entirely within *e*, and - [(3.3)](#3.3) there is no array object that satisfies these constraints nested within *e*[.](#3.sentence-1) [*Note [3](#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]](basic.life "6.8.4 Lifetime"))[.](#3.sentence-2) — *end note*] [*Example [1](#example-1)*: // assumes that sizeof(int) is equal to 4templatestruct AlignedUnion {alignas(T...) unsigned char data[max(sizeof(T)...)];};int f() { AlignedUnion au; int *p = new (au.data) int; // OK, au.data provides storagechar *c = new (au.data) char(); // OK, ends lifetime of *pchar *d = new (au.data + 1) char(); return *c + *d; // OK}struct A { unsigned char a[32]; };struct B { unsigned char b[16]; };alignas(int) A a; B *b = new (a.a + 8) B; // a.a provides storage for *bint *p = new (b->b + 4) int; // b->b provides storage for *p// a.a does not provide storage for *p (directly),// but *p is nested within a (see below) — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3531) An object *a* is [*nested within*](#def:nested_within "6.8.2 Object model [intro.object]") another object *b* if - [(4.1)](#4.1) *a* is a subobject of *b*, or - [(4.2)](#4.2) *b* provides storage for *a*, or - [(4.3)](#4.3) there exists an object *c* where *a* is nested within *c*, and *c* is nested within *b*[.](#4.sentence-1) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3545) For every object x, there is some object called the[*complete object of*](#def:complete_object_of "6.8.2 Object model [intro.object]") x, determined as follows: - [(5.1)](#5.1) If x is a complete object, then the complete object of x is itself[.](#5.1.sentence-1) - [(5.2)](#5.2) Otherwise, the complete object of x is the complete object of the (unique) object that contains x[.](#5.2.sentence-1) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3558) If a complete object, a member subobject, or an array element is of class type, its type is considered the [*most derived class*](#def:most_derived_class "6.8.2 Object model [intro.object]"), 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 a[*most derived object*](#def:most_derived_object "6.8.2 Object model [intro.object]")[.](#6.sentence-1) [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3565) A [*potentially-overlapping subobject*](#def:potentially-overlapping_subobject "6.8.2 Object model [intro.object]") is either: - [(7.1)](#7.1) a base class subobject, or - [(7.2)](#7.2) a non-static data member declared with the [no_unique_address](dcl.attr.nouniqueaddr "9.13.11 No unique address attribute [dcl.attr.nouniqueaddr]") attribute[.](#7.sentence-1) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3573) An object has nonzero size if it - [(8.1)](#8.1) is not a potentially-overlapping subobject, or - [(8.2)](#8.2) is not of class type, or - [(8.3)](#8.3) is of a class type with virtual member functions or virtual base classes, or - [(8.4)](#8.4) has subobjects of nonzero size or unnamed bit-fields of nonzero length[.](#8.sentence-1) 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[.](#8.sentence-2) Otherwise, the circumstances under which the object has zero size are implementation-defined[.](#8.sentence-3) Unless it is a [bit-field](class.bit "11.4.10 Bit-fields [class.bit]"), 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[.](#8.sentence-4) An object of trivially copyable or standard-layout type ([[basic.types.general]](basic.types.general "6.9.1 General")) shall occupy contiguous bytes of storage[.](#8.sentence-5) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3600) An object is a [*potentially non-unique object*](#def:object,potentially_non-unique "6.8.2 Object model [intro.object]") if it is - [(9.1)](#9.1) a string literal object ([[lex.string]](lex.string "5.13.5 String literals")), - [(9.2)](#9.2) the backing array of an initializer list ([[dcl.init.ref]](dcl.init.ref "9.5.4 References")), or - [(9.3)](#9.3) the object introduced by a call to std​::​meta​::​reflect_constant_array or std​::​meta​::​​reflect_constant_string ([[meta.reflection.array]](meta.reflection.array "21.4.15 Promoting to static storage arrays")), or - [(9.4)](#9.4) a subobject thereof[.](#9.sentence-1) [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3614) 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[.](#10.sentence-1) Two objects with overlapping lifetimes that are not bit-fields may have the same address if - [(10.1)](#10.1) one is nested within the other, - [(10.2)](#10.2) at least one is a subobject of zero size and they are not of similar types ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")), or - [(10.3)](#10.3) they are both potentially non-unique objects; otherwise, they have distinct addresses and occupy disjoint bytes of storage[.](#10.sentence-2)[20](#footnote-20 "Under the “as-if” rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference ([intro.execution]).") [*Example [2](#example-2)*: static const char test1 = 'x';static const char test2 = 'x';const bool b = &test1 != &test2; // always truestatic const char (&r) [] = "x";static const char *s = "x";static std::initializer_list il = { 'x' };const bool b2 = r != il.begin(); // unspecified resultconst bool b3 = r != s; // unspecified resultconst bool b4 = il.begin() != &test1; // always trueconst bool b5 = r != &test1; // always true — *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[.](#10.sentence-3) [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3656) Some operations are described as[*implicitly creating objects*](#def:object,implicit_creation "6.8.2 Object model [intro.object]") within a specified region of storage[.](#11.sentence-1) 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]](basic.types.general#term.implicit.lifetime.type "6.9.1 General")) in its specified region of storage if doing so would result in the program having defined behavior[.](#11.sentence-2) If no such set of objects would give the program defined behavior, the behavior of the program is undefined[.](#11.sentence-3) If multiple such sets of objects would give the program defined behavior, it is unspecified which such set of objects is created[.](#11.sentence-4) [*Note [4](#note-4)*: Such operations do not start the lifetimes of subobjects of such objects that are not themselves of implicit-lifetime types[.](#11.sentence-5) — *end note*] [12](#12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3674) Further, after implicitly creating objects within a specified region of storage, some operations are described as producing a pointer to a[*suitable created object*](#def:object,suitable_created "6.8.2 Object model [intro.object]")[.](#12.sentence-1) 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[.](#12.sentence-2) If no such pointer value would give the program defined behavior, the behavior of the program is undefined[.](#12.sentence-3) If multiple such pointer values would give the program defined behavior, it is unspecified which such pointer value is produced[.](#12.sentence-4) [13](#13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3687) [*Example [3](#example-3)*: #include struct X { int a, b; }; X *make_x() {// The call to std​::​malloc implicitly creates an object of type X// and its subobjects a and b, and returns a pointer to that X object// (or an object that is pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4 Compound types")) with it),// in order to give the subsequent class member access operations// defined behavior. X *p = (X*)std::malloc(sizeof(struct X)); p->a = 1; p->b = 2; return p;} — *end example*] [14](#14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3706) Except during constant evaluation, an operation that begins the lifetime of an array of unsigned char or std​::​byte implicitly creates objects within the region of storage occupied by the array[.](#14.sentence-1) [*Note [5](#note-5)*: The array object provides storage for these objects[.](#14.sentence-2) — *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[.](#14.sentence-3) [*Note [6](#note-6)*: Some functions in the C++ standard library implicitly create objects ([[obj.lifetime]](obj.lifetime "20.2.6 Explicit lifetime management"), [[c.malloc]](c.malloc "20.2.12 C library memory allocation"), [[mem.res.public]](mem.res.public "20.5.2.2 Public member functions"), [[bit.cast]](bit.cast "22.11.3 Function template bit_­cast"), [[cstring.syn]](cstring.syn "27.5.1 Header synopsis"))[.](#14.sentence-4) — *end note*] [20)](#footnote-20)[20)](#footnoteref-20) Under the “as-if” rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))[.](#footnote-20.sentence-1)