Files
2025-10-25 03:02:53 +03:00

361 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.2Object model[intro.object]") is created
by a [definition](basic.def "6.2Declarations and definitions[basic.def]"),
by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")),
by an operation that implicitly creates objects (see below),
when implicitly changing the active member of a [union](class.union "11.5Unions[class.union]"),
or
when a temporary object is created ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#1.sentence-2)
An object occupies a region of storage
in its period of construction ([[class.cdtor]](class.cdtor "11.9.5Construction and destruction")),
throughout its [lifetime](basic.life "6.8.4Lifetime[basic.life]"),
and
in its period of destruction ([[class.cdtor]](class.cdtor "11.9.5Construction 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.1Preamble"))[.](#1.sentence-6)
An object has a storage
duration ([[basic.stc]](basic.stc "6.8.6Storage duration")) which influences its
lifetime ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#1.sentence-7)
An object has a
type ([[basic.types]](basic.types "6.9Types"))[.](#1.sentence-8)
[*Note [2](#note-2)*:
Some objects are
polymorphic ([[class.virtual]](class.virtual "11.7.3Virtual 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.2Object model[intro.object]")[.](#2.sentence-1)
A subobject can be
a [*member subobject*](#def:member_subobject "6.8.2Object model[intro.object]") ([[class.mem]](class.mem "11.4Class members")), a [*base class subobject*](#def:base_class_subobject "6.8.2Object model[intro.object]") ([[class.derived]](class.derived "11.7Derived 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.2Object 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.8New"))
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.1Header <cstddef> synopsis")),
that array [*provides storage*](#def:provides_storage "6.8.2Object 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.4Lifetime"))[.](#3.sentence-2)
— *end note*]
[*Example [1](#example-1)*: // assumes that sizeof(int) is equal to 4template<typename ...T>struct AlignedUnion {alignas(T...) unsigned char data[max(sizeof(T)...)];};int f() { AlignedUnion<int, char> 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.2Object 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.2Object 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.2Object 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.2Object 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.2Object 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.11No 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.10Bit-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.1General")) 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.2Object model[intro.object]") if it is
- [(9.1)](#9.1)
a string literal object ([[lex.string]](lex.string "5.13.5String literals")),
- [(9.2)](#9.2)
the backing array of an initializer list ([[dcl.init.ref]](dcl.init.ref "9.5.4References")), 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.15Promoting 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.6Qualification 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<char> 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.2Object 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.1General"))
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.2Object 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 <cstdlib>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.4Compound 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.6Explicit lifetime management"), [[c.malloc]](c.malloc "20.2.12C library memory allocation"), [[mem.res.public]](mem.res.public "20.5.2.2Public member functions"), [[bit.cast]](bit.cast "22.11.3Function template bit_­cast"), [[cstring.syn]](cstring.syn "27.5.1Header <cstring> 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.1Sequential execution"))[.](#footnote-20.sentence-1)