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

495 lines
23 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.stc]
# 6 Basics [[basic]](./#basic)
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc)
### 6.8.6 Storage duration [basic.stc]
#### [6.8.6.1](#general) General [[basic.stc.general]](basic.stc.general)
[1](#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[.](#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)](#general-1.1)
static storage duration
- [(1.2)](#general-1.2)
thread storage duration
- [(1.3)](#general-1.3)
automatic storage duration
- [(1.4)](#general-1.4)
dynamic storage duration
[*Note [1](#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"))[.](#general-1.sentence-2)
— *end note*]
[2](#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"))[.](#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"))[.](#general-2.sentence-2)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4274)
The storage duration categories apply to references as well[.](#general-3.sentence-1)
[4](#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"))[.](#general-4.sentence-1)
#### [6.8.6.2](#static) Static storage duration [[basic.stc.static]](basic.stc.static)
[1](#static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4285)
All variables which
- [(1.1)](#static-1.1)
do not have thread storage duration and
- [(1.2)](#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]")[.](#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"))[.](#static-1.sentence-2)
[2](#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")[.](#static-2.sentence-1)
[3](#static-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4305)
[*Note [1](#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[.](#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"))[.](#static-3.sentence-2)
— *end note*]
#### [6.8.6.3](#thread) Thread storage duration [[basic.stc.thread]](basic.stc.thread)
[1](#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]")[.](#thread-1.sentence-1)
The storage for these entities lasts for the duration of
the thread in which they are created[.](#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[.](#thread-1.sentence-3)
[2](#thread-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4328)
[*Note [1](#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"))[.](#thread-2.sentence-1)
— *end note*]
#### [6.8.6.4](#auto) Automatic storage duration [[basic.stc.auto]](basic.stc.auto)
[1](#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]")[.](#auto-1.sentence-1)
The storage
for such variables lasts until the block in which they are created exits[.](#auto-1.sentence-2)
[*Note [1](#auto-note-1)*:
These variables are initialized and destroyed as described in [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#auto-1.sentence-3)
— *end note*]
Variables that belong to a parameter scope also have automatic storage duration[.](#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"))[.](#auto-1.sentence-5)
[2](#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")[.](#auto-2.sentence-1)
#### [6.8.6.5](#dynamic) Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic)
#### [6.8.6.5.1](#dynamic.general) General [[basic.stc.dynamic.general]](basic.stc.dynamic.general)
[1](#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"))[.](#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[][.](#dynamic.general-1.sentence-2)
[*Note [1](#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[.](#dynamic.general-1.sentence-3)
— *end note*]
[2](#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[.](#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"))[.](#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[.](#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[][.](#dynamic.general-2.sentence-4)
[*Note [2](#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[.](#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[.](#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[.](#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"))[.](#dynamic.general-2.sentence-8)
[3](#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]](#dynamic.allocation "6.8.6.5.2Allocation functions") and [[basic.stc.dynamic.deallocation]](#dynamic.deallocation "6.8.6.5.3Deallocation functions"),
the behavior is undefined[.](#dynamic.general-3.sentence-1)
#### [6.8.6.5.2](#dynamic.allocation) Allocation functions [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation)
[1](#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[.](#dynamic.allocation-1.sentence-1)
The return type shall be void*[.](#dynamic.allocation-1.sentence-2)
The first
parameter shall have type std::size_t ([[support.types]](support.types "17.2Common definitions"))[.](#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"))[.](#dynamic.allocation-1.sentence-4)
The value of the first parameter
is interpreted as the requested size of the allocation[.](#dynamic.allocation-1.sentence-5)
An allocation
function can be a function template[.](#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)[.](#dynamic.allocation-1.sentence-7)
Allocation function templates shall have two or more parameters[.](#dynamic.allocation-1.sentence-8)
[2](#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[.](#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[.](#dynamic.allocation-2.sentence-2)
The order,
contiguity, and initial value of storage allocated by successive calls
to an allocation function are unspecified[.](#dynamic.allocation-2.sentence-3)
Even if the size of the space
requested is zero, the request can fail[.](#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[.](#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[.](#dynamic.allocation-2.sentence-6)
The effect of indirecting through a pointer
returned from a request for zero size is undefined[.](#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](#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)](#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[.](#dynamic.allocation-3.1.sentence-1)
- [(3.2)](#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[.](#dynamic.allocation-3.2.sentence-1)
- [(3.3)](#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[.](#dynamic.allocation-3.3.sentence-1)
[4](#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[.](#dynamic.allocation-4.sentence-1)
[*Note [1](#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"))[.](#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[.](#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"))[.](#dynamic.allocation-4.sentence-4)
[5](#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[.](#dynamic.allocation-5.sentence-1)
[*Note [2](#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]](#static "6.8.6.2Static storage duration")),
for objects or references with thread storage duration ([[basic.stc.thread]](#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"))[.](#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](#dynamic.deallocation) Deallocation functions [[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation)
[1](#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[.](#dynamic.deallocation-1.sentence-1)
[2](#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[.](#dynamic.deallocation-2.sentence-1)
A destroying operator delete
shall be a class member function named operator delete[.](#dynamic.deallocation-2.sentence-2)
[*Note [1](#dynamic.deallocation-note-1)*:
Array deletion cannot use a destroying operator delete[.](#dynamic.deallocation-2.sentence-3)
— *end note*]
[3](#dynamic.deallocation-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4564)
Each deallocation function shall return void[.](#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*[.](#dynamic.deallocation-3.sentence-2)
A deallocation function may have more
than one parameter[.](#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)](#dynamic.deallocation-3.1)
optionally, a parameter of type std::destroying_delete_t, then
- [(3.2)](#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)](#dynamic.deallocation-3.3)
optionally, a parameter of type std::align_val_t[.](#dynamic.deallocation-3.sentence-4)
A destroying operator delete shall be a usual deallocation function[.](#dynamic.deallocation-3.sentence-5)
A deallocation function may be an instance of a function
template[.](#dynamic.deallocation-3.sentence-6)
Neither the first parameter nor the return type shall depend
on a template parameter[.](#dynamic.deallocation-3.sentence-7)
A deallocation
function template shall have two or more function parameters[.](#dynamic.deallocation-3.sentence-8)
A template
instance is never a usual deallocation function, regardless of its
signature[.](#dynamic.deallocation-3.sentence-9)
[4](#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[.](#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[.](#dynamic.deallocation-4.sentence-2)
[5](#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[.](#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)