Allocator (C++)
≈ 7 min read
Names in other languages
No names in other languages are held for this entry yet.
Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.
In C++ computer programming, allocators are a component of the C++ Standard Library. The standard library provides several data structures, such as list and set, commonly referred to as containers. A common trait among these containers is their ability to change size during the execution of the program. To achieve this, some form of dynamic memory allocation is usually required. Allocators handle all the requests for allocation and deallocation of memory for a given container. The C++ Standard Library provides general-purpose allocators that are used by default; however, custom allocators may also be supplied by the programmer. Allocators were invented by Alexander Stepanov as part of the Standard Template Library (STL). They were originally intended as a means to make the library more flexible and independent of the underlying memory model, allowing programmers to utilize custom pointer and reference types with the library. However, in the process of adopting STL into the C++ standard, the C++ standardization committee realized that a complete abstraction of the memory model would incur unacceptable performance penalties. To remedy this, the requirements of allocators were made more restrictive. As a result, the level of customization provided by allocators is more limited than was originally envisioned by Stepanov.…
In C++ computer programming, allocators are a component of the C++ Standard Library. The standard library provides several data structures, such as list and set, commonly referred to as containers. A common trait among these containers is their ability to change size during the execution of the program. To achieve this, some form of dynamic memory allocation is usually required. Allocators handle all the requests for allocation and deallocation of memory for a given container. The C++ Standard Library provides general-purpose allocators that are used by default; however, custom allocators may also be supplied by the programmer. Allocators were invented by Alexander Stepanov as part of the Standard Template Library (STL). They were originally intended as a means to make the library more flexible and independent of the underlying memory model, allowing programmers to utilize custom pointer and reference types with the library. However, in the process of adopting STL into the C++ standard, the C++ standardization committee realized that a complete abstraction of the memory model would incur unacceptable performance penalties. To remedy this, the requirements of allocators were made more restrictive. As a result, the level of customization provided by allocators is more limited than was originally envisioned by Stepanov. Nevertheless, there are many scenarios where customized allocators are desirable. Some of the most common reasons for writing custom allocators include improving performance of allocations by using memory pools, and encapsulating access to different types of memory, like shared memory or garbage-collected memory. In particular, programs with many frequent allocations of small amounts of memory may benefit greatly from specialized allocators, both in terms of running time and memory footprint. Although a conforming standard library implementation is allowed to assume that the allocator's A::pointer and A::const_pointer are simply typedefs for T* and const T* , library implementors are encouraged to support more general allocators. An allocator, A , for objects of type T must have a member function with the signature A::pointer A::allocate(A::size_type n, A ::const_pointer hint = 0); This function returns a pointer to the first element of a newly allocated array large enough to contain n objects of type T ; only the memory is allocated, and the objects are not constructed. Moreover, an optional pointer argument (that points to an object already allocated by A ) can be used as a hint to the implementation about where the new memory should be allocated in order to improve locality. However, the implementation is free to ignore the argument. The corresponding void A::deallocate(A::pointer p, A::size_type n) member function accepts any pointer that was returned from a previous invocation of the A::allocate member function and the number of elements to deallocate (but not destruct). The A::max_size() member function returns the largest number of objects of type T that could be expected to be successfully allocated by an invocation of A::allocate ; the value returned is typically A::size_type(-1) / sizeof(T) . Also, the A::address member function returns an A::pointer denoting the address of an object, given an A::reference . Object construction and destruction is performed separately from allocation and deallocation. The allocator is required to have two member functions, A::construct and A::destroy (both functions have been deprecated in C++17, and removed in C++20), which handles object construction and destruction, respectively. The semantics of the functions should be equivalent to the following: template void A::construct(A::pointer p, A::const_reference t) { new ((void*) p) T(t); } template void A::destroy(A::pointer p){ ((T*)p)->~T(); } The above code uses the placement new syntax, and calls the destructor directly. Allocators should be copy-constructible. An allocator for objects of type T can be constructed from an allocator for objects of type U . If an allocator, A , allocates a region of memory, R , then R can only be deallocated by an allocator that compares equal to A . Allocators are required to supply a template class member rebind : template struct A::rebind { using other = A ; }; which enables the possibility of obtaining a related allocator, parameterized in terms of a different type. For example, given an allocator type IntAllocator for objects of type int , a related allocator type for objects of type long could be obtained using IntAllocator::rebind ::other . namespace std { template > class vector; // ... namespace pmr { template using vector = ::std::vector >; // ... } } Like all C++ class templates, instantiations of standard library containers with different allocator arguments are distinct types. A function expecting an std::vector argument will therefore only accept a vector instantiated with the default allocator. import import std; using std::bad_alloc; using std::string; using std::string_view; using __gnu_cxx::new_allocator; class RequiredAllocation { private: static constexpr string_view DEFAULT_NAME = "Hello, world!\n"; public: const string name; RequiredAllocation(string_view name = DEFAULT_NAME): name{string(name)} { std::println("RequiredAllocation constructor"); } ~RequiredAllocation() { std::println("RequiredAllocation destructor"); } }; void alloc(new_allocator & all, size_t size, void* p, RequiredAllocation& t) { try { all.allocate(size, p); std::println("{}", all->max_size()); for (char c : t.name) { std::println(c); } } catch (const bad_alloc& e) std::println(stderr, "Bad allocation exception: {}", e.what()); } } int main() { new_allocator all; RequiredAllocation t; void* pt = &t; // When new can find no store to allocate, // by default, the allocator throws std::bad_alloc constexpr size_t BAD_SIZE = 1073741824; alloc(all, BAD_SIZE, &pt, t); constexpr size_t SMALL_SIZE = 1; alloc(all, SMALL_SIZE, &pt, t); return 0; } ==External links== CodeGuru: Allocators (STL) . An introductory article "C++ Standard Allocator, An Introduction and Implementation". A custom allocator implementation based on malloc
Text derived from https://en.wikipedia.org/w/index.php?oldid=1367288989 under CC BY-SA 4.0; modifications have been made.