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

1956 lines
91 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.

[basic.memobj]
# 6 Basics [[basic]](./#basic)
## 6.8 Memory and objects [basic.memobj]
### [6.8.1](#intro.memory) Memory model [[intro.memory]](intro.memory)
[1](#intro.memory-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3348)
The fundamental storage unit in the C++ memory model is the[*byte*](#def:byte "6.8.1Memory model[intro.memory]")[.](#intro.memory-1.sentence-1)
A byte is at least large enough to contain
the ordinary literal encoding of any element of the basicliteral character set ([[lex.charset]](lex.charset "5.3.1Character sets"))
and the eight-bit code units of the UnicodeUTF-8 encoding form
and is composed of a contiguous sequence of
bits,[19](#footnote-19 "The number of bits in a byte is reported by the macro CHAR_­BIT in the header <climits>.") the number of which is implementation-defined[.](#intro.memory-1.sentence-2)
The memory available to a C++ program consists of one or more sequences of
contiguous bytes[.](#intro.memory-1.sentence-3)
Every byte has a unique address[.](#intro.memory-1.sentence-4)
[2](#intro.memory-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3370)
[*Note [1](#intro.memory-note-1)*:
The representation of types is described
in [[basic.types.general]](basic.types.general "6.9.1General")[.](#intro.memory-2.sentence-1)
— *end note*]
[3](#intro.memory-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3376)
A [*memory location*](#def:memory_location "6.8.1Memory model[intro.memory]") is
the storage occupied by the object representation of
either an object of scalar type that is not a bit-field
or a maximal sequence of adjacent bit-fields all having nonzero width[.](#intro.memory-3.sentence-1)
[*Note [2](#intro.memory-note-2)*:
Various
features of the language, such as references and virtual functions, might
involve additional memory locations that are not accessible to programs but are
managed by the implementation[.](#intro.memory-3.sentence-2)
— *end note*]
Two or more [threads of
execution](intro.multithread#def:thread_of_execution "6.10.2Multi-threaded executions and data races[intro.multithread]") can access separate memory
locations without interfering with each other[.](#intro.memory-3.sentence-3)
[4](#intro.memory-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3391)
[*Note [3](#intro.memory-note-3)*:
Thus a bit-field and an adjacent non-bit-field are in separate memory
locations, and therefore can be concurrently updated by two threads of execution
without interference[.](#intro.memory-4.sentence-1)
The same applies to two bit-fields, if one is declared
inside a nested struct declaration and the other is not, or if the two are
separated by a zero-length bit-field declaration, or if they are separated by a
non-bit-field declaration[.](#intro.memory-4.sentence-2)
It is not safe to concurrently update two bit-fields
in the same struct if all fields between them are also bit-fields of nonzero
width[.](#intro.memory-4.sentence-3)
— *end note*]
[5](#intro.memory-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3403)
[*Example [1](#intro.memory-example-1)*:
A class declared asstruct {char a; int b:5,
c:11, :0,
d:8; struct {int ee:8;} e;}; contains four separate memory locations: The member a and bit-fieldsd and e.ee are each separate memory locations, and can be
modified concurrently without interfering with each other[.](#intro.memory-5.sentence-1)
The bit-fieldsb and c together constitute the fourth memory location[.](#intro.memory-5.sentence-2)
The
bit-fields b and c cannot be concurrently modified, butb and a, for example, can be[.](#intro.memory-5.sentence-3)
— *end example*]
[19)](#footnote-19)[19)](#footnoteref-19)
The number of bits in a byte is reported by the macroCHAR_BIT in the header [<climits>](climits.syn#header:%3cclimits%3e "17.3.6Header <climits> synopsis[climits.syn]")[.](#footnote-19.sentence-1)
### [6.8.2](#intro.object) Object model [[intro.object]](intro.object)
[1](#intro.object-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[.](#intro.object-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"))[.](#intro.object-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"))[.](#intro.object-1.sentence-3)
[*Note [1](#intro.object-note-1)*:
A function is not an object, regardless of whether or not it
occupies storage in the way that objects do[.](#intro.object-1.sentence-4)
— *end note*]
The properties of an
object are determined when the object is created[.](#intro.object-1.sentence-5)
An object can have a
name ([[basic.pre]](basic.pre "6.1Preamble"))[.](#intro.object-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"))[.](#intro.object-1.sentence-7)
An object has a
type ([[basic.types]](basic.types "6.9Types"))[.](#intro.object-1.sentence-8)
[*Note [2](#intro.object-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[.](#intro.object-1.sentence-9)
— *end note*]
[2](#intro.object-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]")[.](#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[.](#intro.object-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]")[.](#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)](#intro.object-2.1)
the lifetime of *e*'s containing object has begun and not ended, and
- [(2.2)](#intro.object-2.2)
the storage for the new object exactly overlays the storage location associated with *e*, and
- [(2.3)](#intro.object-2.3)
the new object is of the same type as *e* (ignoring cv-qualification)[.](#intro.object-2.sentence-4)
[3](#intro.object-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)](#intro.object-3.1)
the lifetime of *e* has begun and not ended, and
- [(3.2)](#intro.object-3.2)
the storage for the new object fits entirely within *e*, and
- [(3.3)](#intro.object-3.3)
there is no array object that satisfies these constraints nested within *e*[.](#intro.object-3.sentence-1)
[*Note [3](#intro.object-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"))[.](#intro.object-3.sentence-2)
— *end note*]
[*Example [1](#intro.object-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](#intro.object-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)](#intro.object-4.1)
*a* is a subobject of *b*, or
- [(4.2)](#intro.object-4.2)
*b* provides storage for *a*, or
- [(4.3)](#intro.object-4.3)
there exists an object *c* where *a* is nested within *c*,
and *c* is nested within *b*[.](#intro.object-4.sentence-1)
[5](#intro.object-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)](#intro.object-5.1)
If x is a complete object, then the complete object
of x is itself[.](#intro.object-5.1.sentence-1)
- [(5.2)](#intro.object-5.2)
Otherwise, the complete object of x is the complete object
of the (unique) object that contains x[.](#intro.object-5.2.sentence-1)
[6](#intro.object-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]")[.](#intro.object-6.sentence-1)
[7](#intro.object-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)](#intro.object-7.1)
a base class subobject, or
- [(7.2)](#intro.object-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[.](#intro.object-7.sentence-1)
[8](#intro.object-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3573)
An object has nonzero size if it
- [(8.1)](#intro.object-8.1)
is not a potentially-overlapping subobject, or
- [(8.2)](#intro.object-8.2)
is not of class type, or
- [(8.3)](#intro.object-8.3)
is of a class type with virtual member functions or virtual base classes, or
- [(8.4)](#intro.object-8.4)
has subobjects of nonzero size or unnamed bit-fields of nonzero length[.](#intro.object-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[.](#intro.object-8.sentence-2)
Otherwise, the circumstances under which the object has zero size
are implementation-defined[.](#intro.object-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[.](#intro.object-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[.](#intro.object-8.sentence-5)
[9](#intro.object-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)](#intro.object-9.1)
a string literal object ([[lex.string]](lex.string "5.13.5String literals")),
- [(9.2)](#intro.object-9.2)
the backing array of an initializer list ([[dcl.init.ref]](dcl.init.ref "9.5.4References")), or
- [(9.3)](#intro.object-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)](#intro.object-9.4)
a subobject thereof[.](#intro.object-9.sentence-1)
[10](#intro.object-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[.](#intro.object-10.sentence-1)
Two objects
with overlapping lifetimes
that are not bit-fields
may have the same address if
- [(10.1)](#intro.object-10.1)
one is nested within the other,
- [(10.2)](#intro.object-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)](#intro.object-10.3)
they are both potentially non-unique objects;
otherwise, they have distinct addresses
and occupy disjoint bytes of storage[.](#intro.object-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](#intro.object-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[.](#intro.object-10.sentence-3)
[11](#intro.object-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[.](#intro.object-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[.](#intro.object-11.sentence-2)
If no such set of objects would give the program defined behavior,
the behavior of the program is undefined[.](#intro.object-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[.](#intro.object-11.sentence-4)
[*Note [4](#intro.object-note-4)*:
Such operations do not start the lifetimes of subobjects of such objects
that are not themselves of implicit-lifetime types[.](#intro.object-11.sentence-5)
— *end note*]
[12](#intro.object-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]")[.](#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[.](#intro.object-12.sentence-2)
If no such pointer value would give the program defined behavior,
the behavior of the program is undefined[.](#intro.object-12.sentence-3)
If multiple such pointer values would give the program defined behavior,
it is unspecified which such pointer value is produced[.](#intro.object-12.sentence-4)
[13](#intro.object-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3687)
[*Example [3](#intro.object-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](#intro.object-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[.](#intro.object-14.sentence-1)
[*Note [5](#intro.object-note-5)*:
The array object provides storage for these objects[.](#intro.object-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[.](#intro.object-14.sentence-3)
[*Note [6](#intro.object-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"))[.](#intro.object-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)
### [6.8.3](#basic.align) Alignment [[basic.align]](basic.align)
[1](#basic.align-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3727)
Object types have [*alignment requirements*](#def:alignment_requirement,implementation-defined "6.8.3Alignment[basic.align]") ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"), [[basic.compound]](basic.compound "6.9.4Compound types"))
which place restrictions on the addresses at which an object of that type
may be allocated[.](#basic.align-1.sentence-1)
An [*alignment*](#def:alignment "6.8.3Alignment[basic.align]") is an implementation-defined
integer value representing the number of bytes between successive addresses
at which a given object can be allocated[.](#basic.align-1.sentence-2)
An object type imposes an alignment
requirement on every object of that type; stricter alignment can be requested
using the alignment specifier ([[dcl.align]](dcl.align "9.13.2Alignment specifier"))[.](#basic.align-1.sentence-3)
Attempting to create an object ([[intro.object]](#intro.object "6.8.2Object model")) in storage that
does not meet the alignment requirements of the object's type
is undefined behavior[.](#basic.align-1.sentence-4)
[2](#basic.align-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3739)
A [*fundamental alignment*](#def:alignment,fundamental "6.8.3Alignment[basic.align]") is represented by an alignment
less than or equal to the greatest alignment supported by the implementation in
all contexts, which is equal toalignof(std::max_align_t) ([[support.types]](support.types "17.2Common definitions"))[.](#basic.align-2.sentence-1)
The alignment required for a type may be different when it is used as the type
of a complete object and when it is used as the type of a subobject[.](#basic.align-2.sentence-2)
[*Example [1](#basic.align-example-1)*: struct B { long double d; };struct D : virtual B { char c; };
When D is the type of a complete object, it will have a subobject of
type B, so it must be aligned appropriately for a long double[.](#basic.align-2.sentence-3)
If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different
subobject, reducing the alignment requirements on the D subobject[.](#basic.align-2.sentence-4)
— *end example*]
The result of the alignof operator reflects the alignment
requirement of the type in the complete-object case[.](#basic.align-2.sentence-5)
[3](#basic.align-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3761)
An [*extended alignment*](#def:alignment,extended "6.8.3Alignment[basic.align]") is represented by an alignment
greater than alignof(std::max_align_t)[.](#basic.align-3.sentence-1)
It is implementation-defined
whether any extended alignments are supported and the contexts in which they are
supported ([[dcl.align]](dcl.align "9.13.2Alignment specifier"))[.](#basic.align-3.sentence-2)
A type having an extended alignment
requirement is an [*over-aligned type*](#def:type,over-aligned "6.8.3Alignment[basic.align]")[.](#basic.align-3.sentence-3)
[*Note [1](#basic.align-note-1)*:
Every over-aligned type is or contains a class type
to which extended alignment applies (possibly through a non-static data member)[.](#basic.align-3.sentence-4)
— *end note*]
A [*new-extended alignment*](#def:alignment,new-extended "6.8.3Alignment[basic.align]") is represented by
an alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__ ([[cpp.predefined]](cpp.predefined "15.12Predefined macro names"))[.](#basic.align-3.sentence-5)
[4](#basic.align-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3774)
Alignments are represented as values of the type std::size_t[.](#basic.align-4.sentence-1)
Valid alignments include only those values returned by an alignof expression for the fundamental types plus an additional implementation-defined
set of values, which may be empty[.](#basic.align-4.sentence-2)
Every alignment value shall be a non-negative integral power of two[.](#basic.align-4.sentence-3)
[5](#basic.align-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3782)
Alignments have an order from [*weaker*](#def:alignment,weaker "6.8.3Alignment[basic.align]") to[*stronger*](#def:alignment,stronger "6.8.3Alignment[basic.align]") or [*stricter*](#def:alignment,stricter "6.8.3Alignment[basic.align]") alignments[.](#basic.align-5.sentence-1)
Stricter
alignments have larger alignment values[.](#basic.align-5.sentence-2)
An address that satisfies an alignment
requirement also satisfies any weaker valid alignment requirement[.](#basic.align-5.sentence-3)
[6](#basic.align-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3788)
The alignment requirement of a complete type can be queried using analignof expression ([[expr.alignof]](expr.alignof "7.6.2.6Alignof"))[.](#basic.align-6.sentence-1)
Furthermore,
the narrow character types ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types")) shall have the weakest
alignment requirement[.](#basic.align-6.sentence-2)
[*Note [2](#basic.align-note-2)*:
This enables the ordinary character types to be used as the
underlying type for an aligned memory area ([[dcl.align]](dcl.align "9.13.2Alignment specifier"))[.](#basic.align-6.sentence-3)
— *end note*]
[7](#basic.align-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3798)
Comparing alignments is meaningful and provides the obvious results:
- [(7.1)](#basic.align-7.1)
Two alignments are equal when their numeric values are equal[.](#basic.align-7.1.sentence-1)
- [(7.2)](#basic.align-7.2)
Two alignments are different when their numeric values are not equal[.](#basic.align-7.2.sentence-1)
- [(7.3)](#basic.align-7.3)
When an alignment is larger than another it represents a stricter alignment[.](#basic.align-7.3.sentence-1)
[8](#basic.align-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3807)
[*Note [3](#basic.align-note-3)*:
The runtime pointer alignment function ([[ptr.align]](ptr.align "20.2.5Pointer alignment"))
can be used to obtain an aligned pointer within a buffer;
an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2Alignment specifier"))
can be used to align storage explicitly[.](#basic.align-8.sentence-1)
— *end note*]
[9](#basic.align-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3815)
If a request for a specific extended alignment in a specific context is not
supported by an implementation, the program is ill-formed[.](#basic.align-9.sentence-1)
### [6.8.4](#basic.life) Lifetime [[basic.life]](basic.life)
[1](#basic.life-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3821)
In this subclause, “before” and “after” refer to the “happens before”
relation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#basic.life-1.sentence-1)
[2](#basic.life-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3825)
The [*lifetime*](#def:lifetime "6.8.4Lifetime[basic.life]") of an object or reference is a runtime property of the
object or reference[.](#basic.life-2.sentence-1)
A variable is said to have [*vacuous initialization*](#def:initialization,vacuous "6.8.4Lifetime[basic.life]") if it is default-initialized, no other initialization is performed, and,
if it is of class type or a (possibly multidimensional) array thereof,
a trivial constructor of that class type is selected for
the default-initialization[.](#basic.life-2.sentence-2)
The lifetime of an object of type T begins when:
- [(2.1)](#basic.life-2.1)
storage with the proper alignment and size
for type T is obtained, and
- [(2.2)](#basic.life-2.2)
its initialization (if any) is complete
(including vacuous initialization) ([[dcl.init]](dcl.init "9.5Initializers")),
except that if the object is a union member or subobject thereof,
its lifetime only begins if that union member is the
initialized member in the union ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"), [[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
or as described in[[class.union]](class.union "11.5Unions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"), and [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator"),
and except as described in [[allocator.members]](allocator.members "20.2.10.2Members")[.](#basic.life-2.sentence-3)
The lifetime of an object *o* of type T ends when:
- [(2.3)](#basic.life-2.3)
if T is a non-class type, the object is destroyed, or
- [(2.4)](#basic.life-2.4)
if T is a class type, the destructor call starts, or
- [(2.5)](#basic.life-2.5)
the storage which the object occupies is released,
or is reused by an object that is not nested within *o* ([[intro.object]](#intro.object "6.8.2Object model"))[.](#basic.life-2.sentence-4)
When evaluating a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]"),
storage is considered reused after it is returned from the allocation function,
but before the evaluation of the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New"))[.](#basic.life-2.sentence-5)
[*Example [1](#basic.life-example-1)*: struct S {int m;};
void f() { S x{1}; new(&x) S(x.m); // undefined behavior} — *end example*]
[3](#basic.life-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3870)
The lifetime of a reference begins when its initialization is complete[.](#basic.life-3.sentence-1)
The lifetime of a reference ends as if it were a scalar object requiring storage[.](#basic.life-3.sentence-2)
[4](#basic.life-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3875)
[*Note [1](#basic.life-note-1)*:
[[class.base.init]](class.base.init "11.9.3Initializing bases and members") describes the lifetime of base and member subobjects[.](#basic.life-4.sentence-1)
— *end note*]
[5](#basic.life-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3881)
The properties ascribed to objects and references throughout this document
apply for a given object or reference only during its lifetime[.](#basic.life-5.sentence-1)
[*Note [2](#basic.life-note-2)*:
In particular, before the lifetime of an object starts and after its
lifetime ends there are significant restrictions on the use of the
object, as described below, in [[class.base.init]](class.base.init "11.9.3Initializing bases and members"), and
in [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#basic.life-5.sentence-2)
Also, the behavior of an object under construction
and destruction can differ from the behavior of an object whose
lifetime has started and not ended[.](#basic.life-5.sentence-3)
[[class.base.init]](class.base.init "11.9.3Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describe the behavior of an object during its periods
of construction and destruction[.](#basic.life-5.sentence-4)
— *end note*]
[6](#basic.life-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3895)
A program may end the lifetime of an object of class type without invoking the
destructor, by reusing or releasing the storage as described above[.](#basic.life-6.sentence-1)
[*Note [3](#basic.life-note-3)*:
A [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]") ([[expr.delete]](expr.delete "7.6.2.9Delete")) invokes the destructor
prior to releasing the storage[.](#basic.life-6.sentence-2)
— *end note*]
In this case, the destructor is not implicitly invoked[.](#basic.life-6.sentence-3)
[*Note [4](#basic.life-note-4)*:
The correct behavior of a program often depends on
the destructor being invoked for each object of class type[.](#basic.life-6.sentence-4)
— *end note*]
[7](#basic.life-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3908)
Before the lifetime of an object has started but after the storage which
the object will occupy has been allocated[21](#footnote-21 "For example, before the dynamic initialization of an object with static storage duration ([basic.start.dynamic]).") or after the lifetime of an object has ended and before the storage
which the object occupied is reused or released, any pointer that represents the address of
the storage location where the object will be or was located may be
used but only in limited ways[.](#basic.life-7.sentence-1)
For an object under construction or destruction, see [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#basic.life-7.sentence-2)
Otherwise, such
a pointer refers to allocated
storage ([[basic.stc.dynamic.allocation]](#basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions")), and using the pointer as
if the pointer were of type void* is
well-defined[.](#basic.life-7.sentence-3)
Indirection through such a pointer is permitted but the resulting lvalue may only be used in
limited ways, as described below[.](#basic.life-7.sentence-4)
The
program has undefined behavior if
- [(7.1)](#basic.life-7.1)
the pointer is used as the operand of a [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]"),
- [(7.2)](#basic.life-7.2)
the pointer is used to access a non-static data member or call a
non-static member function of the object, or
- [(7.3)](#basic.life-7.3)
the pointer is implicitly converted ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")) to a pointer
to a virtual base class, or
- [(7.4)](#basic.life-7.4)
the pointer is used as the operand of a static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast")), except when the conversion
is to pointer to cv void, or to pointer to cv void and subsequently to pointer to cv char, cv unsigned char, or cv std::byte ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis")), or
- [(7.5)](#basic.life-7.5)
the pointer is used as the operand of a dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast"))[.](#basic.life-7.sentence-5)
[*Example [2](#basic.life-example-2)*: #include <cstdlib>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; // reuses storage --- ends the lifetime of *this f(); // undefined behavior... = this; // OK, this points to valid memory}void g() {void* p = std::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 memory pb->f(); // undefined behavior: lifetime of *pb has ended} — *end example*]
[8](#basic.life-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3978)
Similarly, before the lifetime of an object has started but after the
storage which the object will occupy has been allocated or after the
lifetime of an object has ended and before the storage which the object
occupied is reused or released, any glvalue that refers to the original
object may be used but only in limited ways[.](#basic.life-8.sentence-1)
For an object under construction or destruction, see [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#basic.life-8.sentence-2)
Otherwise, such
a glvalue refers to
allocated storage ([[basic.stc.dynamic.allocation]](#basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions")), and using the
properties of the glvalue that do not depend on its value is
well-defined[.](#basic.life-8.sentence-3)
The program has undefined behavior if
- [(8.1)](#basic.life-8.1)
the glvalue is used to access the object, or
- [(8.2)](#basic.life-8.2)
the glvalue is used to call a non-static member function of the object, or
- [(8.3)](#basic.life-8.3)
the glvalue is bound to a reference to a virtual base class ([[dcl.init.ref]](dcl.init.ref "9.5.4References")), or
- [(8.4)](#basic.life-8.4)
the glvalue is used as the operand of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast")) or as the operand oftypeid[.](#basic.life-8.sentence-4)
[*Note [5](#basic.life-note-5)*:
Therefore, undefined behavior results
if an object that is being constructed in one thread is referenced from another
thread without adequate synchronization[.](#basic.life-8.sentence-5)
— *end note*]
[9](#basic.life-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4005)
An object o1 is [*transparently replaceable*](#def:transparently_replaceable "6.8.4Lifetime[basic.life]") by an object o2 if
- [(9.1)](#basic.life-9.1)
the storage that o2 occupies exactly overlays
the storage that o1 occupied, and
- [(9.2)](#basic.life-9.2)
o1 and o2 are of the same type
(ignoring the top-level cv-qualifiers), and
- [(9.3)](#basic.life-9.3)
o1 is not a const, complete object, and
- [(9.4)](#basic.life-9.4)
neither o1 nor o2 is a potentially-overlapping subobject ([[intro.object]](#intro.object "6.8.2Object model")), and
- [(9.5)](#basic.life-9.5)
either o1 and o2 are both complete objects, oro1 and o2 are direct subobjects of objects p1 and p2, respectively,
and p1 is transparently replaceable by p2[.](#basic.life-9.sentence-1)
[10](#basic.life-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4024)
After the lifetime of an object has ended and before the storage which the
object occupied is reused or released, if a new object is created at the
storage location which the original object occupied and the original object was
transparently replaceable by the new object, a pointer that pointed to the
original object, a reference that referred to the original object, or the name
of the original object will automatically refer to the new object and, once the
lifetime of the new object has started, can be used to manipulate the new
object[.](#basic.life-10.sentence-1)
[*Example [3](#basic.life-example-3)*: struct C {int i; void f(); const C& operator=( const C& );};
const C& C::operator=( const C& other) {if ( this != &other ) {this->~C(); // lifetime of *this endsnew (this) C(other); // new object of type C created f(); // well-defined}return *this;} C c1;
C c2;
c1 = c2; // well-defined c1.f(); // well-defined; c1 refers to a new object of type C — *end example*]
[*Note [6](#basic.life-note-6)*:
If these conditions are not met,
a pointer to the new object can be obtained from
a pointer that represents the address of its storage
by calling std::launder ([[ptr.launder]](ptr.launder "17.6.5Pointer optimization barrier"))[.](#basic.life-10.sentence-2)
— *end note*]
[11](#basic.life-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4064)
If a program ends the lifetime of an object of type T with
static ([[basic.stc.static]](#basic.stc.static "6.8.6.2Static storage duration")), thread ([[basic.stc.thread]](#basic.stc.thread "6.8.6.3Thread storage duration")),
or automatic ([[basic.stc.auto]](#basic.stc.auto "6.8.6.4Automatic storage duration"))
storage duration and if T has a non-trivial destructor,[22](#footnote-22 "That is, an object for which a destructor will be called implicitly—upon exit from the block for an object with automatic storage duration, upon exit from the thread for an object with thread storage duration, or upon exit from the program for an object with static storage duration.") and another object of the original type does not occupy
that same storage location when the implicit destructor call takes
place, the behavior of the program is undefined[.](#basic.life-11.sentence-1)
This is true
even if the block is exited with an exception[.](#basic.life-11.sentence-2)
[*Example [4](#basic.life-example-4)*: class T { };struct B {~B();};
void h() { B b; new (&b) T;} // undefined behavior at block exit — *end example*]
[12](#basic.life-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4095)
Creating a new object within the storage that a const, complete
object with static, thread, or automatic storage duration occupies,
or within the storage that such a const object used to occupy before
its lifetime ended, results in undefined behavior[.](#basic.life-12.sentence-1)
[*Example [5](#basic.life-example-5)*: struct B { B(); ~B();};
const B b;
void h() { b.~B(); new (const_cast<B*>(&b)) const B; // undefined behavior} — *end example*]
[21)](#footnote-21)[21)](#footnoteref-21)
For example, before the dynamic initialization of
an object with static storage duration ([[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"))[.](#footnote-21.sentence-1)
[22)](#footnote-22)[22)](#footnoteref-22)
That
is, an object for which a destructor will be called
implicitly—upon exit from the block for an object with
automatic storage duration, upon exit from the thread for an object with
thread storage duration, or upon exit from the program for an object
with static storage duration[.](#footnote-22.sentence-1)
### [6.8.5](#basic.indet) Indeterminate and erroneous values [[basic.indet]](basic.indet)
[1](#basic.indet-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4119)
When storage for an object with automatic or dynamic storage duration
is obtained,
the bytes comprising the storage for the object
have the following initial value:
- [(1.1)](#basic.indet-1.1)
If the object has dynamic storage duration, or
is the object associated with a variable or function parameter
whose first declaration is marked with
the [[indeterminate]] attribute ([[dcl.attr.indet]](dcl.attr.indet "9.13.6Indeterminate storage")),
the bytes have [*indeterminate values*](#def:value,indeterminate "6.8.5Indeterminate and erroneous values[basic.indet]");
- [(1.2)](#basic.indet-1.2)
otherwise, the bytes have [*erroneous values*](#def:value,erroneous "6.8.5Indeterminate and erroneous values[basic.indet]"),
where each value is determined by the implementation
independently of the state of the program[.](#basic.indet-1.sentence-1)
If no initialization is performed for an object (including subobjects),
such a byte retains its initial value
until that value is replaced ([[dcl.init.general]](dcl.init.general "9.5.1General"), [[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))[.](#basic.indet-1.sentence-2)
If any bit in the value representation has an indeterminate value,
the object has an indeterminate value;
otherwise, if any bit in the value representation has an erroneous value,
the object has an erroneous value ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion"))[.](#basic.indet-1.sentence-3)
[*Note [1](#basic.indet-note-1)*:
Objects with static or thread storage duration are zero-initialized,
see [[basic.start.static]](basic.start.static "6.10.3.2Static initialization")[.](#basic.indet-1.sentence-4)
— *end note*]
[2](#basic.indet-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4148)
Except in the following cases,
if an indeterminate value is produced by an evaluation,
the behavior is undefined, and
if an erroneous value is produced by an evaluation,
the behavior is erroneous and
the result of the evaluation is the value so produced but is not erroneous:
- [(2.1)](#basic.indet-2.1)
If an indeterminate or erroneous value of
unsigned ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis"))
is produced by the evaluation of:
* [(2.1.1)](#basic.indet-2.1.1)
the second or third operand of a [conditional expression](expr.cond "7.6.16Conditional operator[expr.cond]"),
* [(2.1.2)](#basic.indet-2.1.2)
the right operand of a [comma expression](expr.comma "7.6.20Comma operator[expr.comma]"),
* [(2.1.3)](#basic.indet-2.1.3)
the operand of a cast or conversion ([[conv.integral]](conv.integral "7.3.9Integral conversions"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"))
to an unsigned ordinary character type
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis")), or
* [(2.1.4)](#basic.indet-2.1.4)
a [discarded-value expression](expr.context#def:discarded-value_expression "7.2.3Context dependence[expr.context]"),
then the result of the operation is an indeterminate value or
that erroneous value, respectively[.](#basic.indet-2.1.sentence-1)
- [(2.2)](#basic.indet-2.2)
If an indeterminate or erroneous value of
unsigned ordinary character type or std::byte type
is produced by the evaluation of
the right operand of a simple assignment operator ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))
whose first operand is an lvalue of
unsigned ordinary character type or std::byte type,
an indeterminate value or that erroneous value, respectively, replaces
the value of the object referred to by the left operand[.](#basic.indet-2.2.sentence-1)
- [(2.3)](#basic.indet-2.3)
If an indeterminate or erroneous value of unsigned ordinary character type
is produced by the evaluation of the initialization expression
when initializing an object of unsigned ordinary character type,
that object is initialized to an indeterminate
value or that erroneous value, respectively[.](#basic.indet-2.3.sentence-1)
- [(2.4)](#basic.indet-2.4)
If an indeterminate value of
unsigned ordinary character type or std::byte type
is produced by the evaluation of the initialization expression
when initializing an object of std::byte type,
that object is initialized to an indeterminate value or
that erroneous value, respectively[.](#basic.indet-2.4.sentence-1)
Converting an indeterminate or erroneous value of
unsigned ordinary character type or std::byte type
produces an indeterminate or erroneous value, respectively[.](#basic.indet-2.sentence-2)
In the latter case,
the result of the conversion is the value of the converted operand[.](#basic.indet-2.sentence-3)
[*Example [1](#basic.indet-example-1)*: int f(bool b) {unsigned char *c = new unsigned char; unsigned char d = *c; // OK, d has an indeterminate valueint e = d; // undefined behaviorreturn b ? d : 0; // undefined behavior if b is true}int g(bool b) {unsigned char c; unsigned char d = c; // no erroneous behavior, but d has an erroneous value assert(c == d); // holds, both integral promotions have erroneous behaviorint e = d; // erroneous behaviorreturn b ? d : 0; // erroneous behavior if b is true}void h() {int d1, d2; int e1 = d1; // erroneous behaviorint e2 = d1; // erroneous behavior assert(e1 == e2); // holds assert(e1 == d1); // holds, erroneous behavior assert(e2 == d1); // holds, erroneous behavior std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but d2 has an erroneous value assert(e1 == d2); // holds, erroneous behavior assert(e2 == d2); // holds, erroneous behavior} — *end example*]
### [6.8.6](#basic.stc) Storage duration [[basic.stc]](basic.stc)
#### [6.8.6.1](#basic.stc.general) General [[basic.stc.general]](basic.stc.general)
[1](#basic.stc.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4244)
The [*storage duration*](#def:storage_duration "6.8.6.1General[basic.stc.general]") is the property of an object that defines the minimum
potential lifetime of the storage containing the object[.](#basic.stc.general-1.sentence-1)
The storage
duration is determined by the construct used to create the object and is
one of the following:
- [(1.1)](#basic.stc.general-1.1)
static storage duration
- [(1.2)](#basic.stc.general-1.2)
thread storage duration
- [(1.3)](#basic.stc.general-1.3)
automatic storage duration
- [(1.4)](#basic.stc.general-1.4)
dynamic storage duration
[*Note [1](#basic.stc.general-note-1)*:
After the duration of a region of storage has ended,
the use of pointers to that region of storage is limited ([[basic.compound]](basic.compound "6.9.4Compound types"))[.](#basic.stc.general-1.sentence-2)
— *end note*]
[2](#basic.stc.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4261)
Static, thread, and automatic storage durations are associated with objects
introduced by declarations ([[basic.def]](basic.def "6.2Declarations and definitions")) and
with temporary objects ([[class.temporary]](#class.temporary "6.8.7Temporary objects"))[.](#basic.stc.general-2.sentence-1)
The dynamic storage duration
is associated with objects created by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")) or
with implicitly created objects ([[intro.object]](#intro.object "6.8.2Object model"))[.](#basic.stc.general-2.sentence-2)
[3](#basic.stc.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4274)
The storage duration categories apply to references as well[.](#basic.stc.general-3.sentence-1)
[4](#basic.stc.general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4277)
The storage duration of subobjects and reference members
is that of their complete object ([[intro.object]](#intro.object "6.8.2Object model"))[.](#basic.stc.general-4.sentence-1)
#### [6.8.6.2](#basic.stc.static) Static storage duration [[basic.stc.static]](basic.stc.static)
[1](#basic.stc.static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4285)
All variables which
- [(1.1)](#basic.stc.static-1.1)
do not have thread storage duration and
- [(1.2)](#basic.stc.static-1.2)
belong to a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6Namespace scope")) or
are first declared with
the static or extern keywords ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))
have [*static storage duration*](#def:storage_duration,static "6.8.6.2Static storage duration[basic.stc.static]")[.](#basic.stc.static-1.sentence-1)
The storage for these entities lasts for the duration of the
program ([[basic.start.static]](basic.start.static "6.10.3.2Static initialization"), [[basic.start.term]](basic.start.term "6.10.3.4Termination"))[.](#basic.stc.static-1.sentence-2)
[2](#basic.stc.static-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4299)
If a variable with static storage duration has initialization or a
destructor with side effects, it shall not be eliminated even if it
appears to be unused, except that a class object or its copy/move may be
eliminated as specified in [[class.copy.elision]](class.copy.elision "11.9.6Copy/move elision")[.](#basic.stc.static-2.sentence-1)
[3](#basic.stc.static-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4305)
[*Note [1](#basic.stc.static-note-1)*:
The keyword static can be used to declare
a block variable ([[basic.scope.block]](basic.scope.block "6.4.3Block scope")) with static storage duration;[[stmt.dcl]](stmt.dcl "8.10Declaration statement") and [[basic.start.term]](basic.start.term "6.10.3.4Termination") describe the
initialization and destruction of such variables[.](#basic.stc.static-3.sentence-1)
The keyword static applied to
a class data member in a class definition
gives the data member static storage duration ([[class.static.data]](class.static.data "11.4.9.3Static data members"))[.](#basic.stc.static-3.sentence-2)
— *end note*]
#### [6.8.6.3](#basic.stc.thread) Thread storage duration [[basic.stc.thread]](basic.stc.thread)
[1](#basic.stc.thread-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4320)
All variables declared with the thread_local keyword have[*thread storage duration*](#def:storage_duration,thread "6.8.6.3Thread storage duration[basic.stc.thread]")[.](#basic.stc.thread-1.sentence-1)
The storage for these entities lasts for the duration of
the thread in which they are created[.](#basic.stc.thread-1.sentence-2)
There is a distinct object or reference
per thread, and use of the declared name refers to the entity associated with
the current thread[.](#basic.stc.thread-1.sentence-3)
[2](#basic.stc.thread-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4328)
[*Note [1](#basic.stc.thread-note-1)*:
A variable with thread storage duration is initialized as specified
in [[basic.start.static]](basic.start.static "6.10.3.2Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10Declaration statement") and, if constructed, is destroyed on thread exit ([[basic.start.term]](basic.start.term "6.10.3.4Termination"))[.](#basic.stc.thread-2.sentence-1)
— *end note*]
#### [6.8.6.4](#basic.stc.auto) Automatic storage duration [[basic.stc.auto]](basic.stc.auto)
[1](#basic.stc.auto-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4337)
Variables that belong to a block scope and are
not explicitly declared static, thread_local, or extern have[*automatic storage duration*](#def:storage_duration,automatic "6.8.6.4Automatic storage duration[basic.stc.auto]")[.](#basic.stc.auto-1.sentence-1)
The storage
for such variables lasts until the block in which they are created exits[.](#basic.stc.auto-1.sentence-2)
[*Note [1](#basic.stc.auto-note-1)*:
These variables are initialized and destroyed as described in [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#basic.stc.auto-1.sentence-3)
— *end note*]
Variables that belong to a parameter scope also have automatic storage duration[.](#basic.stc.auto-1.sentence-4)
The storage for a function parameter lasts until
immediately after its destruction ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#basic.stc.auto-1.sentence-5)
[2](#basic.stc.auto-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4350)
If a variable with automatic storage duration has initialization or a destructor with side
effects, an implementation shall not destroy it before the end of its block
nor eliminate it as an optimization, even if it appears to be
unused, except that a class object or its copy/move may be eliminated as
specified in [[class.copy.elision]](class.copy.elision "11.9.6Copy/move elision")[.](#basic.stc.auto-2.sentence-1)
#### [6.8.6.5](#basic.stc.dynamic) Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic)
#### [6.8.6.5.1](#basic.stc.dynamic.general) General [[basic.stc.dynamic.general]](basic.stc.dynamic.general)
[1](#basic.stc.dynamic.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4362)
Objects can be created dynamically during [program
execution](intro.execution "6.10.1Sequential execution[intro.execution]"), using[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8New")), and destroyed using[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]")*s* ([[expr.delete]](expr.delete "7.6.2.9Delete"))[.](#basic.stc.dynamic.general-1.sentence-1)
A C++ implementation
provides access to, and management of, dynamic storage via
the global [*allocation functions*](#def:allocation_function "6.8.6.5.1General[basic.stc.dynamic.general]")operator new andoperator new[] and
the global [*deallocation functions*](#def:deallocation_function "6.8.6.5.1General[basic.stc.dynamic.general]")operator delete andoperator delete[][.](#basic.stc.dynamic.general-1.sentence-2)
[*Note [1](#basic.stc.dynamic.general-note-1)*:
The non-allocating forms described in [[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms") do not perform allocation or deallocation[.](#basic.stc.dynamic.general-1.sentence-3)
— *end note*]
[2](#basic.stc.dynamic.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4381)
The library provides default definitions for the global allocation and
deallocation functions[.](#basic.stc.dynamic.general-2.sentence-1)
Some global allocation and deallocation
functions are replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5Replaceable function definitions"))[.](#basic.stc.dynamic.general-2.sentence-2)
The following allocation and deallocation functions ([[support.dynamic]](support.dynamic "17.6Dynamic memory management"))
are implicitly declared in global scope in each translation unit of a
program[.](#basic.stc.dynamic.general-2.sentence-3)
void* operator new(std::size_t);void* operator new(std::size_t, std::align_val_t);
void operator delete(void*) noexcept;void operator delete(void*, std::size_t) noexcept;void operator delete(void*, std::align_val_t) noexcept;void operator delete(void*, std::size_t, std::align_val_t) noexcept;
void* operator new[](std::size_t);void* operator new[](std::size_t, std::align_val_t);
void operator delete[](void*) noexcept;void operator delete[](void*, std::size_t) noexcept;void operator delete[](void*, std::align_val_t) noexcept;void operator delete[](void*, std::size_t, std::align_val_t) noexcept;
These implicit declarations introduce only the function namesoperator new,operator new[],operator delete, andoperator delete[][.](#basic.stc.dynamic.general-2.sentence-4)
[*Note [2](#basic.stc.dynamic.general-note-2)*:
The implicit declarations do not introduce
the names std,std::size_t,std::align_val_t,
or any other names that the library uses to
declare these names[.](#basic.stc.dynamic.general-2.sentence-5)
Thus, a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]"),[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]"), or function call that refers to one of
these functions without importing or including the header [<new>](support.dynamic.general#header:%3cnew%3e "17.6.1General[support.dynamic.general]") or importing a C++ library module ([[std.modules]](std.modules "16.4.2.4Modules"))
is well-formed[.](#basic.stc.dynamic.general-2.sentence-6)
However, referring to std or std::size_t or std::align_val_t is ill-formed unless
a standard library declaration ([[cstddef.syn]](cstddef.syn "17.2.1Header <cstddef> synopsis"), [[new.syn]](new.syn "17.6.2Header <new> synopsis"), [[std.modules]](std.modules "16.4.2.4Modules"))
of that name precedes ([[basic.lookup.general]](basic.lookup.general "6.5.1General")) the use of that name[.](#basic.stc.dynamic.general-2.sentence-7)
— *end note*]
Allocation and/or
deallocation functions may also be declared and defined for any
class ([[class.free]](class.free "11.4.11Allocation and deallocation functions"))[.](#basic.stc.dynamic.general-2.sentence-8)
[3](#basic.stc.dynamic.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4433)
If the behavior of an allocation or deallocation function
does not satisfy the semantic constraints
specified in [[basic.stc.dynamic.allocation]](#basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions") and [[basic.stc.dynamic.deallocation]](#basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"),
the behavior is undefined[.](#basic.stc.dynamic.general-3.sentence-1)
#### [6.8.6.5.2](#basic.stc.dynamic.allocation) Allocation functions [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation)
[1](#basic.stc.dynamic.allocation-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4444)
An allocation function that is not a class member function
shall belong to the global scope and not have a name with internal linkage[.](#basic.stc.dynamic.allocation-1.sentence-1)
The return type shall be void*[.](#basic.stc.dynamic.allocation-1.sentence-2)
The first
parameter shall have type std::size_t ([[support.types]](support.types "17.2Common definitions"))[.](#basic.stc.dynamic.allocation-1.sentence-3)
The
first parameter shall not have an associated default
argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#basic.stc.dynamic.allocation-1.sentence-4)
The value of the first parameter
is interpreted as the requested size of the allocation[.](#basic.stc.dynamic.allocation-1.sentence-5)
An allocation
function can be a function template[.](#basic.stc.dynamic.allocation-1.sentence-6)
Such a template shall declare its
return type and first parameter as specified above (that is, template
parameter types shall not be used in the return type and first parameter
type)[.](#basic.stc.dynamic.allocation-1.sentence-7)
Allocation function templates shall have two or more parameters[.](#basic.stc.dynamic.allocation-1.sentence-8)
[2](#basic.stc.dynamic.allocation-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4458)
An allocation function attempts to allocate the requested amount of
storage[.](#basic.stc.dynamic.allocation-2.sentence-1)
If it is successful, it returns the address of the start
of a block of storage whose length in bytes is at least as large
as the requested size[.](#basic.stc.dynamic.allocation-2.sentence-2)
The order,
contiguity, and initial value of storage allocated by successive calls
to an allocation function are unspecified[.](#basic.stc.dynamic.allocation-2.sentence-3)
Even if the size of the space
requested is zero, the request can fail[.](#basic.stc.dynamic.allocation-2.sentence-4)
If the request succeeds, the
value returned by a replaceable allocation function
is a non-null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types"))p0 different from any previously returned value p1,
unless that value p1 was subsequently passed to a
replaceable deallocation function[.](#basic.stc.dynamic.allocation-2.sentence-5)
Furthermore, for the library allocation functions
in [[new.delete.single]](new.delete.single "17.6.3.2Single-object forms") and [[new.delete.array]](new.delete.array "17.6.3.3Array forms"),p0 represents the address of a block of storage disjoint from the storage
for any other object accessible to the caller[.](#basic.stc.dynamic.allocation-2.sentence-6)
The effect of indirecting through a pointer
returned from a request for zero size is undefined[.](#basic.stc.dynamic.allocation-2.sentence-7)[23](#footnote-23 "The intent is to have operator new() implementable by calling std::malloc() or std::calloc(), so the rules are substantially the same. C++ differs from C in requiring a zero request to return a non-null pointer.")
[3](#basic.stc.dynamic.allocation-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4487)
For an allocation function other than
a reserved placement allocation function ([[new.delete.placement]](new.delete.placement "17.6.3.4Non-allocating forms")),
the pointer returned on a successful call
shall represent the address of storage that is aligned as follows:
- [(3.1)](#basic.stc.dynamic.allocation-3.1)
If the allocation function takes an argument
of type std::align_val_t,
the storage will have the alignment specified
by the value of this argument[.](#basic.stc.dynamic.allocation-3.1.sentence-1)
- [(3.2)](#basic.stc.dynamic.allocation-3.2)
Otherwise, if the allocation function is named operator new[],
the storage is aligned for any object that
does not have new-extended alignment ([[basic.align]](#basic.align "6.8.3Alignment")) and
is no larger than the requested size[.](#basic.stc.dynamic.allocation-3.2.sentence-1)
- [(3.3)](#basic.stc.dynamic.allocation-3.3)
Otherwise, the storage is aligned for any object that
does not have new-extended alignment and is of the requested size[.](#basic.stc.dynamic.allocation-3.3.sentence-1)
[4](#basic.stc.dynamic.allocation-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4508)
An allocation function that fails to allocate storage can invoke the
currently installed new-handler function ([[new.handler]](new.handler "17.6.4.3Type new_­handler")), if any[.](#basic.stc.dynamic.allocation-4.sentence-1)
[*Note [1](#basic.stc.dynamic.allocation-note-1)*:
A program-supplied allocation function can obtain the
currently installed new_handler using thestd::get_new_handler function ([[get.new.handler]](get.new.handler "17.6.4.5get_­new_­handler"))[.](#basic.stc.dynamic.allocation-4.sentence-2)
— *end note*]
An allocation function that has a non-throwing
exception specification ([[except.spec]](except.spec "14.5Exception specifications"))
indicates failure by returning
a null pointer value[.](#basic.stc.dynamic.allocation-4.sentence-3)
Any other allocation function
never returns a null pointer value and
indicates failure only by throwing an exception ([[except.throw]](except.throw "14.2Throwing an exception")) of a type
that would match a handler ([[except.handle]](except.handle "14.4Handling an exception")) of typestd::bad_alloc ([[bad.alloc]](bad.alloc "17.6.4.1Class bad_­alloc"))[.](#basic.stc.dynamic.allocation-4.sentence-4)
[5](#basic.stc.dynamic.allocation-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4527)
A global allocation function is only called as the result of a [new
expression](expr.new "7.6.2.8New[expr.new]"), or called directly using the [function call](expr.call "7.6.1.3Function call[expr.call]") syntax, or called indirectly to allocate storage for
a coroutine state ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions")),
or called indirectly through calls to the
functions in the C++ standard library[.](#basic.stc.dynamic.allocation-5.sentence-1)
[*Note [2](#basic.stc.dynamic.allocation-note-2)*:
In particular, a
global allocation function is not called to allocate storage
for objects with static storage duration ([[basic.stc.static]](#basic.stc.static "6.8.6.2Static storage duration")),
for objects or references with thread storage duration ([[basic.stc.thread]](#basic.stc.thread "6.8.6.3Thread storage duration")),
for objects of type std::type_info ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")),
for an object of type std::contracts::contract_violation when a contract violation occurs ([[basic.contract.eval]](basic.contract.eval "6.11.2Evaluation")), or
for an exception object ([[except.throw]](except.throw "14.2Throwing an exception"))[.](#basic.stc.dynamic.allocation-5.sentence-2)
— *end note*]
[23)](#footnote-23)[23)](#footnoteref-23)
The intent is
to have operator new() implementable by
calling std::malloc() or std::calloc(), so the rules are
substantially the same[.](#footnote-23.sentence-1)
C++ differs from C in requiring a zero request
to return a non-null pointer[.](#footnote-23.sentence-2)
#### [6.8.6.5.3](#basic.stc.dynamic.deallocation) Deallocation functions [[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation)
[1](#basic.stc.dynamic.deallocation-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4547)
A deallocation function that is not a class member function
shall belong to the global scope and not have a name with internal linkage[.](#basic.stc.dynamic.deallocation-1.sentence-1)
[2](#basic.stc.dynamic.deallocation-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4552)
A deallocation function
is a [*destroying operator delete*](#def:operator_delete,destroying "6.8.6.5.3Deallocation functions[basic.stc.dynamic.deallocation]") if it has at least two parameters
and its second parameter
is of type std::destroying_delete_t[.](#basic.stc.dynamic.deallocation-2.sentence-1)
A destroying operator delete
shall be a class member function named operator delete[.](#basic.stc.dynamic.deallocation-2.sentence-2)
[*Note [1](#basic.stc.dynamic.deallocation-note-1)*:
Array deletion cannot use a destroying operator delete[.](#basic.stc.dynamic.deallocation-2.sentence-3)
— *end note*]
[3](#basic.stc.dynamic.deallocation-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4564)
Each deallocation function shall return void[.](#basic.stc.dynamic.deallocation-3.sentence-1)
If the function is a destroying operator delete
declared in class type C,
the type of its first parameter shall be C*;
otherwise, the type of its first
parameter shall be void*[.](#basic.stc.dynamic.deallocation-3.sentence-2)
A deallocation function may have more
than one parameter[.](#basic.stc.dynamic.deallocation-3.sentence-3)
A [*usual deallocation function*](#def:usual_deallocation_function "6.8.6.5.3Deallocation functions[basic.stc.dynamic.deallocation]") is a deallocation function
whose parameters after the first are
- [(3.1)](#basic.stc.dynamic.deallocation-3.1)
optionally, a parameter of type std::destroying_delete_t, then
- [(3.2)](#basic.stc.dynamic.deallocation-3.2)
optionally, a parameter of type std::size_t,[24](#footnote-24 "The global operator delete(void*, std::size_­t) precludes use of an allocation function void operator new(std::size_­t, std::size_­t) as a placement allocation function ([diff.cpp11.basic]).") then
- [(3.3)](#basic.stc.dynamic.deallocation-3.3)
optionally, a parameter of type std::align_val_t[.](#basic.stc.dynamic.deallocation-3.sentence-4)
A destroying operator delete shall be a usual deallocation function[.](#basic.stc.dynamic.deallocation-3.sentence-5)
A deallocation function may be an instance of a function
template[.](#basic.stc.dynamic.deallocation-3.sentence-6)
Neither the first parameter nor the return type shall depend
on a template parameter[.](#basic.stc.dynamic.deallocation-3.sentence-7)
A deallocation
function template shall have two or more function parameters[.](#basic.stc.dynamic.deallocation-3.sentence-8)
A template
instance is never a usual deallocation function, regardless of its
signature[.](#basic.stc.dynamic.deallocation-3.sentence-9)
[4](#basic.stc.dynamic.deallocation-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4600)
If a deallocation function terminates by throwing an exception, the behavior is undefined[.](#basic.stc.dynamic.deallocation-4.sentence-1)
The value of the first argument supplied to a deallocation function may
be a null pointer value; if so, and if the deallocation function is one
supplied in the standard library, the call has no effect[.](#basic.stc.dynamic.deallocation-4.sentence-2)
[5](#basic.stc.dynamic.deallocation-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4606)
If the argument given to a deallocation function in the standard library
is a pointer that is not the null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")), the
deallocation function shall deallocate the storage referenced by the
pointer, ending the duration of the region of storage[.](#basic.stc.dynamic.deallocation-5.sentence-1)
[24)](#footnote-24)[24)](#footnoteref-24)
The global operator delete(void*, std::size_t) precludes use of an
allocation function void operator new(std::size_t, std::size_t) as a placement
allocation function ([[diff.cpp11.basic]](diff.cpp11.basic "C.5.3[basic]: basics"))[.](#footnote-24.sentence-1)
### [6.8.7](#class.temporary) Temporary objects [[class.temporary]](class.temporary)
[1](#class.temporary-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4614)
A [*temporary object*](#def:object,temporary "6.8.7Temporary objects[class.temporary]") is an object created
- [(1.1)](#class.temporary-1.1)
when a prvalue is converted to an xvalue ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) and
- [(1.2)](#class.temporary-1.2)
when needed by the implementation to pass or return an object of suitable type (see below)[.](#class.temporary-1.sentence-1)
Even when the creation of the temporary object is
unevaluated ([[expr.context]](expr.context "7.2.3Context dependence")),
all the semantic restrictions shall be respected as if the temporary object
had been created and later destroyed[.](#class.temporary-1.sentence-2)
[*Note [1](#class.temporary-note-1)*:
This includes accessibility ([[class.access]](class.access "11.8Member access control")) and whether it is deleted,
for the constructor selected and for the destructor[.](#class.temporary-1.sentence-3)
However, in the special
case of the operand of a[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")), no temporary is introduced,
so the foregoing does not apply to such a prvalue[.](#class.temporary-1.sentence-4)
— *end note*]
[2](#class.temporary-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4638)
The materialization of a temporary object is generally
delayed as long as possible
in order to avoid creating unnecessary temporary objects[.](#class.temporary-2.sentence-1)
[*Note [2](#class.temporary-note-2)*:
Temporary objects are materialized:
- [(2.1)](#class.temporary-2.1)
when binding a reference to a prvalue ([[dcl.init.ref]](dcl.init.ref "9.5.4References"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11Const cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")),
- [(2.2)](#class.temporary-2.2)
when performing certain member accesses on a class prvalue ([[expr.ref]](expr.ref "7.6.1.5Class member access"), [[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")),
- [(2.3)](#class.temporary-2.3)
when invoking an implicit object member function on a class prvalue ([[expr.call]](expr.call "7.6.1.3Function call")),
- [(2.4)](#class.temporary-2.4)
when performing an array-to-pointer conversion or subscripting on an array prvalue ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion"), [[expr.sub]](expr.sub "7.6.1.2Subscripting")),
- [(2.5)](#class.temporary-2.5)
when initializing an object of type std::initializer_list<T> from a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")),
- [(2.6)](#class.temporary-2.6)
for certain unevaluated operands ([[expr.typeid]](expr.typeid "7.6.1.8Type identification"), [[expr.sizeof]](expr.sizeof "7.6.2.5Sizeof")), and
- [(2.7)](#class.temporary-2.7)
when a prvalue that has type other than cv void appears as a discarded-value expression ([[expr.context]](expr.context "7.2.3Context dependence"))[.](#class.temporary-2.sentence-2)
— *end note*]
[*Example [1](#class.temporary-example-1)*:
Consider the following code:class X {public: X(int);
X(const X&);
X& operator=(const X&); ~X();};
class Y {public: Y(int);
Y(Y&&); ~Y();};
X f(X);
Y g(Y);
void h() { X a(1);
X b = f(X(2));
Y c = g(Y(3));
a = f(a);}
X(2) is constructed in the space used to hold f()'s argument andY(3) is constructed in the space used to hold g()'s argument[.](#class.temporary-2.sentence-4)
Likewise,f()'s result is constructed directly in b andg()'s result is constructed directly in c[.](#class.temporary-2.sentence-5)
On the other hand, the expressiona = f(a) requires a temporary for
the result of f(a),
which is materialized so that the reference parameter
of X::operator=(const X&) can bind to it[.](#class.temporary-2.sentence-6)
— *end example*]
[3](#class.temporary-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4706)
When an object of class type X is passed to or returned from a potentially-evaluated function call,
if X is
- [(3.1)](#class.temporary-3.1)
a scalar type or
- [(3.2)](#class.temporary-3.2)
a class type that
has at least one eligible copy or move constructor ([[special]](special "11.4.4Special member functions")),
where each such constructor is trivial,
and the destructor of X is either trivial or deleted,
implementations are permitted
to create temporary objects
to hold the function parameter or result object,
as follows:
- [(3.3)](#class.temporary-3.3)
The first such temporary object
is constructed from the function argument or return value, respectively[.](#class.temporary-3.3.sentence-1)
- [(3.4)](#class.temporary-3.4)
Each successive temporary object
is initialized from the previous one
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#class.temporary-3.4.sentence-1)
- [(3.5)](#class.temporary-3.5)
The function parameter or return object is initialized
from the final temporary
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#class.temporary-3.5.sentence-1)
(In all cases, the eligible constructor is used
even if that constructor is inaccessible
or would not be selected by overload resolution
to perform a copy or move of the object)[.](#class.temporary-3.sentence-2)
[*Note [3](#class.temporary-note-3)*:
This latitude is granted to allow objects
to be passed to or returned from functions in registers[.](#class.temporary-3.sentence-3)
— *end note*]
[4](#class.temporary-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4747)
Temporary objects are destroyed as the last step
in evaluating
the full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))
that (lexically) contains the point where
they were created[.](#class.temporary-4.sentence-1)
This is true even if that evaluation ends in throwing an exception[.](#class.temporary-4.sentence-2)
Thevalue computations andside effects of destroying a temporary object
are associated only with the full-expression, not with any specific
subexpression[.](#class.temporary-4.sentence-3)
[5](#class.temporary-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4765)
There are several contexts in which temporaries are destroyed at a different
point than the end of the full-expression[.](#class.temporary-5.sentence-1)
The first context is when a default constructor is called to initialize
an element of an array with no corresponding initializer ([[dcl.init]](dcl.init "9.5Initializers"))[.](#class.temporary-5.sentence-2)
The second context is when a copy constructor is called to copy an element of
an array while the entire array is copied ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"))[.](#class.temporary-5.sentence-3)
In either case, if the constructor has one or more default arguments,
the destruction of every temporary created in a default argument is
sequenced before the construction of the next array element, if any[.](#class.temporary-5.sentence-4)
[6](#class.temporary-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4778)
The third context is when a reference binds to a temporary object[.](#class.temporary-6.sentence-1)[25](#footnote-25 "The same rules apply to initialization of an initializer_­list object ([dcl.init.list]) with its underlying temporary array.")
The temporary object to which the reference is bound or the temporary object
that is the complete object of a subobject to which the reference is bound
persists for the lifetime of the reference if the glvalue
to which the reference is bound
was obtained through one of the following:
- [(6.1)](#class.temporary-6.1)
a temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")),
- [(6.2)](#class.temporary-6.2)
( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ),
where [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is one of these expressions,
- [(6.3)](#class.temporary-6.3)
subscripting ([[expr.sub]](expr.sub "7.6.1.2Subscripting")) of an array operand,
where that operand is one of these expressions,
- [(6.4)](#class.temporary-6.4)
a class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access")) using the . operator
where the left operand is one of these expressions and
the right operand designates a non-static data member of non-reference type,
- [(6.5)](#class.temporary-6.5)
a pointer-to-member operation ([[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")) using the .* operator
where the left operand is one of these expressions and
the right operand is a pointer to data member of non-reference type,
- [(6.6)](#class.temporary-6.6)
a
* [(6.6.1)](#class.temporary-6.6.1)
const_cast ([[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")),
* [(6.6.2)](#class.temporary-6.6.2)
static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast")),
* [(6.6.3)](#class.temporary-6.6.3)
dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast")), or
* [(6.6.4)](#class.temporary-6.6.4)
reinterpret_cast ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10Reinterpret cast"))
converting, without a user-defined conversion,
a glvalue operand that is one of these expressions
to a glvalue that refers
to the object designated by the operand, or
to its complete object or a subobject thereof,
- [(6.7)](#class.temporary-6.7)
a conditional expression ([[expr.cond]](expr.cond "7.6.16Conditional operator")) that is a glvalue
where the second or third operand is one of these expressions, or
- [(6.8)](#class.temporary-6.8)
a comma expression ([[expr.comma]](expr.comma "7.6.20Comma operator")) that is a glvalue
where the right operand is one of these expressions[.](#class.temporary-6.sentence-2)
[*Example [2](#class.temporary-example-2)*: template<typename T> using id = T;
int i = 1;int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as aconst int& b = static_cast<const int&>(0); // temporary int has same lifetime as bint&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended — *end example*]
[*Note [4](#class.temporary-note-4)*:
An explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"))
is interpreted as
a sequence of elementary casts,
covered above[.](#class.temporary-6.sentence-3)
[*Example [3](#class.temporary-example-3)*: const int& x = (const int&)1; // temporary for value 1 has same lifetime as x — *end example*]
— *end note*]
[*Note [5](#class.temporary-note-5)*:
If a temporary object has a reference member initialized by another temporary object,
lifetime extension applies recursively to such a member's initializer[.](#class.temporary-6.sentence-4)
[*Example [4](#class.temporary-example-4)*: struct S {const int& m;};const S& s = S{1}; // both S and int temporaries have lifetime of s — *end example*]
— *end note*]
The exceptions to this lifetime rule are:
- [(6.9)](#class.temporary-6.9)
A temporary object bound to a reference parameter in a function call ([[expr.call]](expr.call "7.6.1.3Function call"))
persists until the completion of the full-expression containing the call[.](#class.temporary-6.9.sentence-1)
- [(6.10)](#class.temporary-6.10)
A temporary object bound to a reference element of
an aggregate of class type initialized from
a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") ([[dcl.init]](dcl.init "9.5Initializers"))
persists until the completion of the full-expression
containing the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")[.](#class.temporary-6.10.sentence-1)
- [(6.11)](#class.temporary-6.11)
A temporary bound to a reference in a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")) persists until the completion of the full-expression containing the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")[.](#class.temporary-6.11.sentence-1)
[*Note [6](#class.temporary-note-6)*:
This might introduce a dangling reference[.](#class.temporary-6.11.sentence-2)
— *end note*]
[*Example [5](#class.temporary-example-5)*: struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} }; // creates dangling reference — *end example*]
[7](#class.temporary-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4886)
The fourth context is when a temporary object
is created in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") of
either a range-based for statement
or an enumerating expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements"))[.](#class.temporary-7.sentence-1)
If such a temporary object would otherwise be destroyed
at the end of the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") full-expression,
the object persists for the lifetime of the reference
initialized by the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]")[.](#class.temporary-7.sentence-2)
[8](#class.temporary-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4896)
The fifth context is when a temporary object is created
in the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") of an iterating or destructuring expansion statement[.](#class.temporary-8.sentence-1)
If such a temporary object would otherwise be destroyed
at the end of that [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"),
the object persists for the lifetime of the reference
initialized by the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"), if any[.](#class.temporary-8.sentence-2)
[9](#class.temporary-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4905)
The sixth context is when a temporary object
is created in a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#class.temporary-9.sentence-1)
Any temporary objects introduced by
the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")*s* for the variables
with unique names
are destroyed at the end of the structured binding declaration[.](#class.temporary-9.sentence-2)
[10](#class.temporary-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4913)
Let x and y each be either
a temporary object whose lifetime is not extended, or
a function parameter[.](#class.temporary-10.sentence-1)
If the lifetimes of x and y end at
the end of the same full-expression, andx is initialized before y, then
the destruction of y is sequenced before that of x[.](#class.temporary-10.sentence-2)
If the lifetime of two or more temporaries
with lifetimes extending beyond the full-expressions in which they were created
ends at the same point,
these temporaries are destroyed at that point in the reverse order of the
completion of their construction[.](#class.temporary-10.sentence-3)
In addition, the destruction of such temporaries shall
take into account the ordering of destruction of objects with static, thread, or
automatic storage duration ([[basic.stc.static]](#basic.stc.static "6.8.6.2Static storage duration"), [[basic.stc.thread]](#basic.stc.thread "6.8.6.3Thread storage duration"), [[basic.stc.auto]](#basic.stc.auto "6.8.6.4Automatic storage duration"));
that is, ifobj1 is an object with the same storage duration as the temporary and
created before the temporary is created
the temporary shall be destroyed beforeobj1 is destroyed;
ifobj2 is an object with the same storage duration as the temporary and
created after the temporary is created
the temporary shall be destroyed afterobj2 is destroyed[.](#class.temporary-10.sentence-4)
[11](#class.temporary-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4944)
[*Example [6](#class.temporary-example-6)*: struct S { S();
S(int); friend S operator+(const S&, const S&); ~S();};
S obj1;const S& cr = S(16)+S(23);
S obj2;
The expressionS(16) + S(23) creates three temporaries:
a first temporaryT1 to hold the result of the expressionS(16),
a second temporaryT2 to hold the result of the expressionS(23),
and a third temporaryT3 to hold the result of the addition of these two expressions[.](#class.temporary-11.sentence-1)
The temporaryT3 is then bound to the referencecr[.](#class.temporary-11.sentence-2)
It is unspecified whetherT1 orT2 is created first[.](#class.temporary-11.sentence-3)
On an implementation whereT1 is created beforeT2,T2 shall be destroyed beforeT1[.](#class.temporary-11.sentence-4)
The temporariesT1 andT2 are bound to the reference parameters ofoperator+;
these temporaries are destroyed at the end of the full-expression
containing the call tooperator+[.](#class.temporary-11.sentence-5)
The temporaryT3 bound to the referencecr is destroyed at the end ofcr's
lifetime, that is, at the end of the program[.](#class.temporary-11.sentence-6)
In addition, the order in whichT3 is destroyed takes into account the destruction order of other objects with
static storage duration[.](#class.temporary-11.sentence-7)
That is, becauseobj1 is constructed beforeT3,
andT3 is constructed beforeobj2,obj2 shall be destroyed beforeT3,
andT3 shall be destroyed beforeobj1[.](#class.temporary-11.sentence-8)
— *end example*]
[25)](#footnote-25)[25)](#footnoteref-25)
The same rules apply to initialization of an initializer_list object ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")) with its
underlying temporary array[.](#footnote-25.sentence-1)