6 Basics [basic]

6.7 Memory and objects [basic.memobj]

6.7.5 Storage duration [basic.stc]

6.7.5.1 General [basic.stc.general]

The storage duration is the property of an object that defines the minimum potential lifetime of the storage containing the object.
The storage duration is determined by the construct used to create the object and is one of the following:
  • static storage duration
  • thread storage duration
  • automatic storage duration
  • dynamic storage duration
[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]).
— end note]
Static, thread, and automatic storage durations are associated with objects introduced by declarations ([basic.def]) and with temporary objects ([class.temporary]).
The dynamic storage duration is associated with objects created by a new-expression ([expr.new]) or with implicitly created objects ([intro.object]).
The storage duration categories apply to references as well.

6.7.5.2 Static storage duration [basic.stc.static]

All variables which have static storage duration.
The storage for these entities lasts for the duration of the program ([basic.start.static], [basic.start.term]).
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].
[Note 1: 
The keyword static can be used to declare a block variable ([basic.scope.block]) with static storage duration; [stmt.dcl] and [basic.start.term] describe the initialization and destruction of such variables.
The keyword static applied to a class data member in a class definition gives the data member static storage duration ([class.static.data]).
— end note]

6.7.5.3 Thread storage duration [basic.stc.thread]

All variables declared with the thread_local keyword have thread storage duration.
The storage for these entities lasts for the duration of the thread in which they are created.
There is a distinct object or reference per thread, and use of the declared name refers to the entity associated with the current thread.
[Note 1: 
A variable with thread storage duration is initialized as specified in [basic.start.static], [basic.start.dynamic], and [stmt.dcl] and, if constructed, is destroyed on thread exit ([basic.start.term]).
— end note]

6.7.5.4 Automatic storage duration [basic.stc.auto]

Variables that belong to a block scope and are not explicitly declared static, thread_local, or extern have automatic storage duration.
The storage for such variables lasts until the block in which they are created exits.
[Note 1: 
These variables are initialized and destroyed as described in [stmt.dcl].
— end note]
Variables that belong to a parameter scope also have automatic storage duration.
The storage for a function parameter lasts until immediately after its destruction ([expr.call]).
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].

6.7.5.5 Dynamic storage duration [basic.stc.dynamic]

6.7.5.5.1 General [basic.stc.dynamic.general]

Objects can be created dynamically during program execution, using new-expressions ([expr.new]), and destroyed using delete-expressions ([expr.delete]).
A C++ implementation provides access to, and management of, dynamic storage via the global allocation functions operator new and operator new[] and the global deallocation functions operator delete and operator delete[].
[Note 1: 
The non-allocating forms described in [new.delete.placement] do not perform allocation or deallocation.
— end note]
The library provides default definitions for the global allocation and deallocation functions.
Some global allocation and deallocation functions are replaceable ([new.delete]); these are attached to the global module ([module.unit]).
A C++ program shall provide at most one definition of a replaceable allocation or deallocation function.
Any such function definition replaces the default version provided in the library ([replacement.functions]).
The following allocation and deallocation functions ([support.dynamic]) are implicitly declared in global scope in each translation unit of a program.
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 names operator new, operator new[], operator delete, and operator delete[].
[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.
Thus, a new-expression, delete-expression, or function call that refers to one of these functions without importing or including the header <new> or importing a C++ library module ([std.modules]) is well-formed.
However, referring to std or std​::​size_t or std​::​align_val_t is ill-formed unless a standard library declaration ([cstddef.syn], [new.syn], [std.modules]) of that name precedes ([basic.lookup.general]) the use of that name.
— end note]
Allocation and/or deallocation functions may also be declared and defined for any class ([class.free]).
If the behavior of an allocation or deallocation function does not satisfy the semantic constraints specified in [basic.stc.dynamic.allocation] and [basic.stc.dynamic.deallocation], the behavior is undefined.

6.7.5.5.2 Allocation functions [basic.stc.dynamic.allocation]

An allocation function that is not a class member function shall belong to the global scope and not have a name with internal linkage.
The return type shall be void*.
The first parameter shall have type std​::​size_t ([support.types]).
The first parameter shall not have an associated default argument ([dcl.fct.default]).
The value of the first parameter is interpreted as the requested size of the allocation.
An allocation function can be a function template.
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).
Allocation function templates shall have two or more parameters.
An allocation function attempts to allocate the requested amount of storage.
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.
The order, contiguity, and initial value of storage allocated by successive calls to an allocation function are unspecified.
Even if the size of the space requested is zero, the request can fail.
If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([basic.compound]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.
Furthermore, for the library allocation functions in [new.delete.single] and [new.delete.array], p0 represents the address of a block of storage disjoint from the storage for any other object accessible to the caller.
The effect of indirecting through a pointer returned from a request for zero size is undefined.24
For an allocation function other than a reserved placement allocation function ([new.delete.placement]), the pointer returned on a successful call shall represent the address of storage that is aligned as follows:
  • 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.
  • 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]) and is no larger than the requested size.
  • Otherwise, the storage is aligned for any object that does not have new-extended alignment and is of the requested size.
An allocation function that fails to allocate storage can invoke the currently installed new-handler function ([new.handler]), if any.
[Note 1: 
A program-supplied allocation function can obtain the currently installed new_handler using the std​::​get_new_handler function ([get.new.handler]).
— end note]
An allocation function that has a non-throwing exception specification ([except.spec]) indicates failure by returning a null pointer value.
Any other allocation function never returns a null pointer value and indicates failure only by throwing an exception ([except.throw]) of a type that would match a handler ([except.handle]) of type std​::​bad_alloc ([bad.alloc]).
A global allocation function is only called as the result of a new expression, or called directly using the function call syntax, or called indirectly to allocate storage for a coroutine state ([dcl.fct.def.coroutine]), or called indirectly through calls to the functions in the C++ standard library.
[Note 2: 
In particular, a global allocation function is not called to allocate storage for objects with static storage duration, for objects or references with thread storage duration, for objects of type std​::​type_info, or for an exception object.
— end note]
24)24)
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.

6.7.5.5.3 Deallocation functions [basic.stc.dynamic.deallocation]

A deallocation function that is not a class member function shall belong to the global scope and not have a name with internal linkage.
A deallocation function is a destroying operator delete if it has at least two parameters and its second parameter is of type std​::​destroying_delete_t.
A destroying operator delete shall be a class member function named operator delete.
[Note 1: 
Array deletion cannot use a destroying operator delete.
— end note]
Each deallocation function shall return void.
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*.
A deallocation function may have more than one parameter.
A usual deallocation function is a deallocation function whose parameters after the first are
  • optionally, a parameter of type std​::​destroying_delete_t, then
  • optionally, a parameter of type std​::​size_t,25 then
  • optionally, a parameter of type std​::​align_val_t.
A destroying operator delete shall be a usual deallocation function.
A deallocation function may be an instance of a function template.
Neither the first parameter nor the return type shall depend on a template parameter.
A deallocation function template shall have two or more function parameters.
A template instance is never a usual deallocation function, regardless of its signature.
If a deallocation function terminates by throwing an exception, the behavior is undefined.
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.
If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value ([basic.compound]), the deallocation function shall deallocate the storage referenced by the pointer, ending the duration of the region of storage.
25)25)
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]).

6.7.5.6 Duration of subobjects [basic.stc.inherit]

The storage duration of subobjects and reference members is that of their complete object ([intro.object]).