|
|
|
Encapsulates strategies for access/addressing, allocation/deallocation and construction/destruction of objects.
Every standard library component that may need to allocate or release storage, fromstd::string,std::vector, and every container, exceptstd::array(since C++11) andstd::inplace_vector(since C++26), tostd::shared_ptr andstd::function(until C++17), does so through anAllocator: an object of a class type that satisfies the following requirements.
The implementation of many allocator requirements is optional because allAllocatorAwareContainer access allocators indirectly throughstd::allocator_traits, andstd::allocator_traits supplies the default implementation of those requirements.
Contents |
Given
T
, anon-const, non-reference type(until C++11)non-const object type(since C++11)(until C++17)cv-unqualified object type(since C++17),A
, anAllocator type for typeT
,A
,B
, the correspondingAllocator type for some cv-unqualified object typeU
(as obtained by rebindingA
),B
,X
,T
obtained by the expression*p,Type-id | Aliased type | Requirements |
---|---|---|
A::pointer (optional) | (unspecified)[1] | |
A::const_pointer (optional) | (unspecified) |
|
A::void_pointer (optional) | (unspecified) |
|
A::const_void_pointer (optional) | (unspecified) |
|
A::value_type | T | |
A::size_type (optional) | (unspecified) |
|
A::difference_type (optional) | (unspecified) |
|
A::template rebind<U>::other (optional)[2] | B |
|
Expression | Return type | Requirements |
---|---|---|
*p | T& | |
*cp | const T& | *cp and*p identify the same object. |
p->m | (as is) | Same as(*p).m, if(*p).m is well-defined. |
cp->m | (as is) | Same as(*cp).m, if(*cp).m is well-defined. |
static_cast<A::pointer>(vp) | (as is) | static_cast<A::pointer>(vp)== p |
static_cast<A::const_pointer>(cvp) | (as is) | static_cast<A::const_pointer>(cvp)== cp |
std::pointer_traits<A::pointer>::pointer_to(r) | (as is) |
Expression | Return type | Requirements |
---|---|---|
a.allocate(n) | A::pointer | Allocates storage suitable for an array object of typeT[n] and creates the array, but does not construct array elements. May throw exceptions. Ifn==0, the return value is unspecified. |
a.allocate(n, cvp)(optional) | Same asa.allocate(n), but may usecvp (nullptr or a pointer obtained froma.allocate()) in unspecified manner to aid locality. | |
a.allocate_at_least(n)(optional)(since C++23) | std::allocation_result <A::pointer> | Allocates storage suitable for an array object of typeT[cnt] and creates the array, but does not construct array elements, then returns{p, cnt}, wherep points to the storage andcnt is not less thann. May throw exceptions. |
a.deallocate(p, n) | (not used) | Deallocates storage pointed top, which must be a value returned by a previous call toallocate orallocate_at_least (since C++23) that has not been invalidated by an intervening call todeallocate .n must match the value previously passed toallocate or be between the request and returned number of elements viaallocate_at_least (may be equal to either bound)(since C++23). Does not throw exceptions. |
a.max_size()(optional) | A::size_type | The largest value that can be passed toA::allocate(). |
a.construct(xp, args...)(optional) | (not used) | Constructs an object of typeX in previously-allocated storage at the address pointed to byxp, usingargs... as the constructor arguments. |
a.destroy(xp)(optional) | (not used) | Destructs an object of typeX pointed to byxp, but does not deallocate any storage. |
Expression | Return type | Requirements |
---|---|---|
a1== a2 | bool |
|
a1!= a2 |
| |
Declaration | Effect | Requirements |
A a1(a) | Copy-constructsa1 such thata1== a. (Note: EveryAllocator also satisfiesCopyConstructible.) |
|
A a1= a | ||
A a(b) | Constructsa such thatB(a)== b andA(b)== a. (Note: This implies that all allocators related by rebind maintain each other's resources, such as memory pools.) |
|
A a1(std::move(a)) | Constructsa1 such that it equals the prior value ofa. |
|
A a1= std::move(a) | ||
A a(std::move(b)) | Constructsa such that it equals the prior value ofA(b). |
|
Type-id | Aliased type | Requirements |
A::is_always_equal (optional) | std::true_type orstd::false_type or derived from such. |
|
Expression | Return type | Description |
---|---|---|
a.select_on_container_copy_construction() (optional) | A |
|
Type-id | Aliased type | Description |
A::propagate_on_container_copy_assignment (optional) | std::true_type orstd::false_type or derived from such. |
|
A::propagate_on_container_move_assignment (optional) |
| |
A::propagate_on_container_swap (optional) |
|
Notes:
rebind
is only optional (provided bystd::allocator_traits) if this allocator is a template of the formSomeAllocator<T, Args>
, whereArgs
is zero or more additional template type parameters.Given
X::void_pointer
,X::const_void_pointer
,X::pointer
, orX::const_pointer
X::const_pointer
, using a sequence ofstatic_casts using only these four types, and the expressionpx1== px2 evaluates totrue.Given
X::void_pointer
X::const_void_pointer
with no change in semantics.Given
X::pointer
X::const_pointer
with no change in semantics.The above requirements make it possible to compareContainer'siterator
s andconst_iterator
s.
Allocator completeness requirementsAn allocator type
| (since C++17) |
EveryAllocator type is eitherstateful orstateless. Generally, a stateful allocator type can have unequal values which denote distinct memory resources, while a stateless allocator type denotes a single memory resource.
Although custom allocators are not required to be stateless, whether and how the use of stateful allocators in the standard library is implementation-defined. Use of unequal allocator values may result in implementation-defined runtime errors or undefined behavior if the implementation does not support such usage. | (until C++11) |
Custom allocators may contain state. Each container or another allocator-aware object stores an instance of the supplied allocator and controls allocator replacement throughstd::allocator_traits. | (since C++11) |
Instances of a stateless allocator type always compare equal. Stateless allocator types are typically implemented as empty classes and suitable forempty base class optimization.
The member type | (since C++11) |
When the member typepointer
is not a raw pointer type, it is commonly referred to as a"fancy pointer". Such pointers were introduced to support segmented memory architectures and are used today to access objects allocated in address spaces that differ from the homogeneous virtual address space that is accessed by raw pointers. An example of a fancy pointer is the mapping address-independent pointerboost::interprocess::offset_ptr
, which makes it possible to allocate node-based data structures such asstd::set in shared memory and memory mapped files mapped in different addresses in every process. Fancy pointers can be used independently of the allocator that provided them, through the class templatestd::pointer_traits(since C++11).The functionstd::to_address can be used to obtain a raw pointer from a fancy pointer.(since C++20)
Use of fancy pointers and customized size/different type in the standard libary are conditionally supported. Implementations may require that member type | (until C++11) |
ConceptFor the definition of the query objectstd::get_allocator, the following exposition-only concept is defined.
The exposition-only concept/*simple-allocator*/ defines the minimal usability constraints of theAllocator requirement. | (since C++26) |
The following standard library components satisfy theAllocator requirements:
the default allocator (class template)[edit] | |
(C++11) | implements multi-level allocator for multi-level containers (class template)[edit] |
(C++17) | an allocator that supports run-time polymorphism based on thestd::pmr::memory_resource it is constructed with (class template)[edit] |
Demonstrates a C++11 allocator, except for[[nodiscard]]
added to match C++20 style.
#include <cstdlib>#include <iostream>#include <limits>#include <new>#include <vector> template<class T>struct Mallocator{typedef T value_type; Mallocator()=default; template<class U>constexpr Mallocator(const Mallocator<U>&)noexcept{} [[nodiscard]] T* allocate(std::size_t n){if(n>std::numeric_limits<std::size_t>::max()/ sizeof(T))throwstd::bad_array_new_length(); if(auto p=static_cast<T*>(std::malloc(n* sizeof(T)))){ report(p, n);return p;} throwstd::bad_alloc();} void deallocate(T* p,std::size_t n)noexcept{ report(p, n,0);std::free(p);}private:void report(T* p,std::size_t n,bool alloc=true)const{std::cout<<(alloc?"Alloc: ":"Dealloc: ")<< sizeof(T)* n<<" bytes at "<<std::hex<<std::showbase<<reinterpret_cast<void*>(p)<<std::dec<<'\n';}}; template<class T,class U>bool operator==(const Mallocator<T>&,const Mallocator<U>&){returntrue;} template<class T,class U>bool operator!=(const Mallocator<T>&,const Mallocator<U>&){returnfalse;} int main(){std::vector<int, Mallocator<int>> v(8); v.push_back(42);}
Possible output:
Alloc: 32 bytes at 0x2020c20Alloc: 64 bytes at 0x2023c60Dealloc: 32 bytes at 0x2020c20Dealloc: 64 bytes at 0x2023c60
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 179 | C++98 | pointer andconst_pointer were notrequired to be comparable with each other | required |
LWG 199 | C++98 | the return value ofa.allocate(0) was unclear | it is unspecified |
LWG 258 (N2436) | C++98 | the equality relationship between allocators were not required to be reflexive, symmetric or transitive | required to be reflexive, symmetric and transitive |
LWG 274 | C++98 | T could be a const-qualified type or reference type,makingstd::allocator possibly ill-formed[1] | prohibited these types |
LWG 2016 | C++11 | the copy, move and swap operations of allocator might be throwing when used | required to be non-throwing |
LWG 2081 | C++98 C++11 | allocators were not required to support copy assignment (C++98) and move assignment (C++11) | required |
LWG 2108 | C++11 | there was no way to show an allocator is stateless | is_always_equal provided |
LWG 2263 | C++11 | the resolution ofLWG issue 179 was accidently dropped in C++11 and not generalized to void_pointer andconst_void_pointer | restored and generalized |
LWG 2447 | C++11 | T could be a volatile-qualified object type | prohibited these types |
LWG 2593 | C++11 | moving from an allocator might modify its value | modification forbidden |
P0593R6 | C++98 | allocate were not required to create anarray object in the storage it allocated | required |
reference
andconst_reference
ofstd::allocator are defined asT&
andconst T&
respectively.T
is a reference type,reference
andconst_reference
are ill-formed because reference to reference cannot be formed (reference collapsing was introduced in C++11).T
is const-qualified,reference
andconst_reference
are the same, and the overload set ofaddress() is ill-formed.