Заголовок <memory> определяет несколько типов и шаблонов функций, которые описывают свойства указателей и типов, подобных указателям, управляют памятью для контейнеров и других типов шаблонов, уничтожают объекты и создают несколько объектов в неинициализированных буферах памяти ([pointer.traits]-[specialized.algorithms]). Заголовок также определяет шаблоны unique_ptr, shared_ptr, weak_ptrшаблоны, и различные функции , которые работают на объектах этих типов ([smartptr]).
namespace std { // [pointer.traits], pointer traits template <class Ptr> struct pointer_traits; template <class T> struct pointer_traits<T*>; // [util.dynamic.safety], pointer safety enum class pointer_safety { relaxed, preferred, strict }; void declare_reachable(void* p); template <class T> T* undeclare_reachable(T* p); void declare_no_pointers(char* p, size_t n); void undeclare_no_pointers(char* p, size_t n); pointer_safety get_pointer_safety() noexcept; // [ptr.align], pointer alignment function void* align(size_t alignment, size_t size, void*& ptr, size_t& space); // [allocator.tag], allocator argument tag struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; // [allocator.uses], uses_allocator template <class T, class Alloc> struct uses_allocator; // [allocator.traits], allocator traits template <class Alloc> struct allocator_traits; // [default.allocator], the default allocator template <class T> class allocator; template <class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept; template <class T, class U> bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // [specialized.algorithms], specialized algorithms template <class T> constexpr T* addressof(T& r) noexcept; template <class T> const T* addressof(const T&&) = delete; template <class ForwardIterator> void uninitialized_default_construct(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void uninitialized_default_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); template <class ForwardIterator> void uninitialized_value_construct(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void uninitialized_value_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, InputIterator last, ForwardIterator result); template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, Size n, ForwardIterator result); template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, InputIterator last, ForwardIterator result); template <class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, Size n, ForwardIterator result); template <class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template <class ExecutionPolicy, class ForwardIterator, class T> void uninitialized_fill(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& x); template <class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x); template <class ExecutionPolicy, class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, const T& x); template <class T> void destroy_at(T* location); template <class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void destroy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator destroy_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator destroy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); // [unique.ptr], class template unique_ptr template <class T> struct default_delete; template <class T> struct default_delete<T[]>; template <class T, class D = default_delete<T>> class unique_ptr; template <class T, class D> class unique_ptr<T[], D>; template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args); template <class T> unique_ptr<T> make_unique(size_t n); template <class T, class... Args> unspecified make_unique(Args&&...) = delete; template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; template <class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& y); // [util.smartptr.weak.bad], class bad_weak_ptr class bad_weak_ptr; // [util.smartptr.shared], class template shared_ptr template<class T> class shared_ptr; // [util.smartptr.shared.create], shared_ptr creation template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // [util.smartptr.shared.cmp], shared_ptr comparisons template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template <class T> bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept; // [util.smartptr.shared.spec], shared_ptr specialized algorithms template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; // [util.smartptr.shared.cast], shared_ptr casts template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; // [util.smartptr.getdeleter], shared_ptr get_deleter template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; // [util.smartptr.shared.io], shared_ptr I/O template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p); // [util.smartptr.weak], class template weak_ptr template<class T> class weak_ptr; // [util.smartptr.weak.spec], weak_ptr specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; // [util.smartptr.ownerless], class template owner_less template<class T = void> struct owner_less; // [util.smartptr.enab], class template enable_shared_from_this template<class T> class enable_shared_from_this; // [util.smartptr.shared.atomic], shared_ptr atomic access template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo); template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r); template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r); template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> bool atomic_compare_exchange_weak( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_weak_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); template<class T> bool atomic_compare_exchange_strong_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); // [util.smartptr.hash], hash support template <class T> struct hash; template <class T, class D> struct hash<unique_ptr<T, D>>; template <class T> struct hash<shared_ptr<T>>; // [allocator.uses.trait], uses_allocator template <class T, class Alloc> inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; }
Шаблон класса pointer_traits предоставляет единый интерфейс для определенных атрибутов типов, подобных указателям.
namespace std { template <class Ptr> struct pointer_traits { using pointer = Ptr; using element_type = see below; using difference_type = see below; template <class U> using rebind = see below; static pointer pointer_to(see below r); }; template <class T> struct pointer_traits<T*> { using pointer = T*; using element_type = T; using difference_type = ptrdiff_t; template <class U> using rebind = U*; static pointer pointer_to(see below r) noexcept; }; }
using element_type = see below;
Type: Ptr::element_type если qualified-id Ptr::element_type действительный и обозначает тип ([temp.deduct]); в противном случае, T if Ptr является экземпляром формы шаблона класса SomePointer<T, Args>, где Args - ноль или более аргументов типа; в противном случае специализация сформирована неправильно.
using difference_type = see below;
Type: Ptr::difference_type если qualified-id Ptr::difference_type действительный и обозначает тип ([temp.deduct]); в противном случае ptrdiff_t.
template <class U> using rebind = see below;
Alias template: Ptr::rebind<U> если qualified-id Ptr::rebind<U> действительный и обозначает тип ([temp.deduct]); в противном случае, SomePointer<U, Args> if Ptr является экземпляром формы шаблона класса SomePointer<T, Args>, где Args - ноль или более аргументов типа; в противном случае создание экземпляра rebind будет некорректным.
static pointer pointer_traits::pointer_to(see below r);
static pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
Remarks: Если element_type есть cv void, то тип r не указан; в противном случае это так element_type&.
Returns: Первая функция-член возвращает указатель на r полученный путем вызова, Ptr::pointer_to(r) через который допустимо косвенное обращение ; экземпляр этой функции плохо сформирован, если Ptr не имеет соответствующей pointer_to статической функции-члена. Вторая функция-член возвращается addressof(r).
Полный объект - это declared reachable когда количество вызовов declare_reachable с аргументом, ссылающимся на объект, превышает количество вызовов undeclare_reachable с аргументом, ссылающимся на объект.
void declare_reachable(void* p);
Requires: p должен быть значением safely-derived pointer или нулевым указателем.
Effects: Если p не равно нулю, то весь объект, на который ссылается, p впоследствии объявляется достижимым ([basic.stc.dynamic.safety]).
Throws: bad_alloc Может вызвать ошибку, если система не может выделить дополнительную память, которая может потребоваться для отслеживания объектов, объявленных достижимыми.
template <class T> T* undeclare_reachable(T* p);
Requires: Если p не равно нулю, весь объект, на который ссылается, p должен быть ранее объявлен достижимым и должен быть live ([basic.life]) с момента вызова до последнего undeclare_reachable(p) вызова объекта.
[ Note: Ожидается, что вызовы to declare_reachable(p) будут потреблять небольшой объем памяти в дополнение к памяти, занятой объектом, на который указывает ссылка, до тех пор, пока не будет обнаружен соответствующий вызов undeclare_reachable(p) . Долгосрочные программы должны согласовывать вызовы. ] — end note
void declare_no_pointers(char* p, size_t n);
Requires: В настоящее время не зарегистрированы байты в указанном диапазоне declare_no_pointers(). Если указанный диапазон находится в выделенном объекте, то он должен полностью находиться в пределах одного выделенного объекта. Объект должен быть жив до соответствующего undeclare_no_pointers() звонка. [ Note: В реализации сборки мусора тот факт, что область в объекте регистрируется, declare_no_pointers() не должен препятствовать сборке объекта. ] — end note
Effects: В n байтах , начиная с p уже не содержат отслеживаемые местоположения указателя, независимо от их типа. Следовательно, косвенное обращение через указатель, расположенный там, не определено, если объект, на который он указывает, был создан глобальным operator new и ранее не объявлен достижимым. [ Note: Это может быть использовано для информирования сборщика мусора или детектора утечек о том, что эту область памяти не нужно отслеживать. ] — end note
[ Note: В некоторых случаях реализациям может потребоваться выделить память. Однако в случае сбоя выделения памяти запрос можно проигнорировать. ] — end note
void undeclare_no_pointers(char* p, size_t n);
Effects: Отменяет регистрацию диапазона, зарегистрированного declare_no_pointers() для уничтожения. Он должен быть вызван до того, как закончится время жизни объекта.
pointer_safety get_pointer_safety() noexcept;
Returns: pointer_safety::strict если в реализации есть strict pointer safety. Это определяется реализацией ли get_pointer_safety возвращается pointer_safety::relaxed или ,pointer_safety::preferred если реализация имеет непринужденную безопасность указателя.221
pointer_safety::preferred может быть возвращено, чтобы указать, что течеискатель работает, чтобы программа могла избежать ложных отчетов об утечках.
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
Effects: Если возможно уместить size байты хранилища, выровненного по, alignment в буфер, на который указывает ptr длина space, функция обновляется, ptr чтобы представить первый возможный адрес такого хранилища, и уменьшается space на количество байтов, используемых для выравнивания. В противном случае функция ничего не делает.
Returns: Нулевой указатель, если запрошенный выровненный буфер не помещается в доступное пространство, в противном случае скорректированное значение ptr.
namespace std {
struct allocator_arg_t { explicit allocator_arg_t() = default; };
inline constexpr allocator_arg_t allocator_arg{};
}
Структура allocator_arg_t - это пустой тип структуры, используемый как уникальный тип для устранения неоднозначности перегрузки конструктора и функции. В частности, несколько типов (см. tuple [tuple]) Имеют конструкторы с allocator_arg_t первым аргументом, за которым сразу следует аргумент типа, удовлетворяющего Allocator требованиям.
template <class T, class Alloc> struct uses_allocator;
Remarks: Автоматически определяет, T есть ли вложенный allocator_type конвертируемый из Alloc. Отвечает BinaryTypeTrait требованиям. Реализация должна обеспечивать определение, производное от true_type того, qualified-id T::allocator_type является ли действительным и обозначает тип ([temp.deduct]), а в is_convertible_v<Alloc, T::allocator_type> != falseпротивном случае оно должно быть производным от false_type. Программа может специализировать этот шаблон, чтобы он производился от true_type определяемого пользователем типа T , который не имеет вложенного, allocator_type но, тем не менее, может быть создан с помощью распределителя, где либо:
первый аргумент конструктора имеет тип, allocator_arg_t а второй аргумент имеет тип Alloc или
последний аргумент конструктора имеет тип Alloc.
Uses-allocator construction с распределителем Alloc относится к построению объекта obj типа Tс использованием аргументов v1, v2, ..., vN конструктора типов V1, V2, ..., VNсоответственно и распределителя alloc типа в Allocсоответствии со следующими правилами:
если uses_allocator_v<T, Alloc> есть false и is_constructible_v<T, V1, V2, ..., VN> есть true, то obj инициализируется как obj(v1, v2, ..., vN);
в противном случае, если uses_allocator_v<T, Alloc> есть true и is_constructible_v<T, allocator_arg_t, Alloc, V1, V2, ..., VN> есть true, то obj инициализируется как obj(allocator_arg, alloc, v1, v2, ..., vN);
в противном случае, если uses_allocator_v<T, Alloc> есть true и is_constructible_v<T, V1, V2, ..., VN, Alloc> есть true, то obj инициализируется как obj(v1, v2, ..., vN, alloc);
в противном случае запрос на построение распределителя использования будет некорректным. [ Note: Произойдет ошибка, если uses_allocator_v<T, Alloc> есть, true но конкретный конструктор не использует распределитель. Это определение предотвращает тихую ошибку передачи распределителя элементу. ] — end note
Шаблон класса allocator_traits предоставляет единый интерфейс для всех типов распределителей. Однако распределитель не может быть неклассовым типом, даже если allocator_traits предоставляет весь требуемый интерфейс. [ Note: Таким образом, всегда можно создать производный класс из распределителя. ] — end note
namespace std { template <class Alloc> struct allocator_traits { using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = see below; using const_pointer = see below; using void_pointer = see below; using const_void_pointer = see below; using difference_type = see below; using size_type = see below; using propagate_on_container_copy_assignment = see below; using propagate_on_container_move_assignment = see below; using propagate_on_container_swap = see below; using is_always_equal = see below; template <class T> using rebind_alloc = see below; template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static pointer allocate(Alloc& a, size_type n); static pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static void deallocate(Alloc& a, pointer p, size_type n); template <class T, class... Args> static void construct(Alloc& a, T* p, Args&&... args); template <class T> static void destroy(Alloc& a, T* p); static size_type max_size(const Alloc& a) noexcept; static Alloc select_on_container_copy_construction(const Alloc& rhs); }; }
using pointer = see below;
Type: Alloc::pointer если qualified-id Alloc::pointer действительный и обозначает тип ([temp.deduct]); в противном случае value_type*.
using const_pointer = see below;
Type: Alloc::const_pointer если qualified-id Alloc::const_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<const value_type>.
using void_pointer = see below;
Type: Alloc::void_pointer если qualified-id Alloc::void_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<void>.
using const_void_pointer = see below;
Type: Alloc::const_void_pointer если qualified-id Alloc::const_void_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<const void>.
using difference_type = see below;
Type: Alloc::difference_type если qualified-id Alloc::difference_type действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::difference_type.
using size_type = see below;
Type: Alloc::size_type если qualified-id Alloc::size_type действительный и обозначает тип ([temp.deduct]); в противном случае make_unsigned_t<difference_type>.
using propagate_on_container_copy_assignment = see below;
Type: Alloc::propagate_on_container_copy_assignment если qualified-id Alloc::propagate_on_container_copy_assignment действительный и обозначает тип ([temp.deduct]); иначе false_type.
using propagate_on_container_move_assignment = see below;
Type: Alloc::propagate_on_container_move_assignment если qualified-id Alloc::propagate_on_container_move_assignment действительный и обозначает тип ([temp.deduct]); иначе false_type.
using propagate_on_container_swap = see below;
Type: Alloc::propagate_on_container_swap если qualified-id Alloc::propagate_on_container_swap действительный и обозначает тип ([temp.deduct]); иначе false_type.
using is_always_equal = see below;
Type: Alloc::is_always_equal если qualified-id Alloc::is_always_equal действительный и обозначает тип ([temp.deduct]); иначе is_empty<Alloc>::type.
template <class T> using rebind_alloc = see below;
Alias template: Alloc::rebind<T>::other если qualified-id Alloc::rebind<T>::other действительный и обозначает тип ([temp.deduct]); в противном случае, Alloc<T, Args> if Alloc является экземпляром формы шаблона класса Alloc<U, Args>, где Args - ноль или более аргументов типа; в противном случае создание экземпляра rebind_alloc будет некорректным.
static pointer allocate(Alloc& a, size_type n);
static pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
Returns: a.allocate(n, hint) если это выражение правильно сформировано; в противном случае a.allocate(n).
static void deallocate(Alloc& a, pointer p, size_type n);
template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);
Effects: Звонит, a.construct(p, std::forward<Args>(args)...) если этот звонок правильно сформирован; в противном случае вызывает ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).
template <class T>
static void destroy(Alloc& a, T* p);
Effects: Звонит, a.destroy(p) если этот звонок правильно сформирован; в противном случае вызывает p->~T().
static size_type max_size(const Alloc& a) noexcept;
Returns: a.max_size() если это выражение правильно сформировано; в противном случае numeric_limits<size_type>::max()/sizeof(value_type).
static Alloc select_on_container_copy_construction(const Alloc& rhs);
Все специализации распределителя по умолчанию удовлетворяют требованиям полноты распределителя ([allocator.requirements.completeness]).
namespace std { template <class T> class allocator { public: using value_type = T; using propagate_on_container_move_assignment = true_type; using is_always_equal = true_type; allocator() noexcept; allocator(const allocator&) noexcept; template <class U> allocator(const allocator<U>&) noexcept; ~allocator(); T* allocate(size_t n); void deallocate(T* p, size_t n); }; }
За исключением деструктора, функции-члены распределителя по умолчанию не должны вводиться data races в результате одновременных вызовов этих функций-членов из разных потоков. Вызов этих функций, которые выделяют или освобождают конкретную единицу памяти, должны происходить в едином общем порядке, и каждый такой вызов освобождения должен происходить до следующего выделения (если таковое имеется) в этом порядке.
T* allocate(size_t n);
Returns: Указатель на начальный элемент массива хранения размера n * sizeof(T), выровненный соответствующим образом для объектов типа T.
Remarks: хранилище получается путем вызова ::operator new, но не указано, когда и как часто вызывается эта функция.
void deallocate(T* p, size_t n);
Requires: p должно быть значением указателя, полученным из allocate(). n должен быть равен значению, переданному в качестве первого аргумента при вызове функции allocate, которая вернулась p.
Remarks: Используется ::operator delete, но не указывается при вызове этой функции.
В этом подпункте имена параметров шаблона используются для выражения требований к типу.
Если указан параметр шаблона алгоритма InputIterator, аргумент шаблона должен удовлетворять требованиям input iterator.
Если параметр шаблона алгоритма назван ForwardIterator, аргумент шаблона должен удовлетворять требованиям a forward iteratorи должен иметь свойство, согласно которому исключения не генерируются при увеличении, назначении, сравнении или косвенном обращении через допустимые итераторы.
Если не указано иное, если в следующих алгоритмах возникает исключение, никаких эффектов не возникает.
template <class T> constexpr T* addressof(T& r) noexcept;
Returns: Фактический адрес объекта или функции, на которые ссылается r, даже при наличии перегруженного operator&.
Remarks: Выражение addressof(E) - это constant subexpression if E - подвыражение константы lvalue.
template <class ForwardIterator>
void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
Effects: Эквивалентен:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type;
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
template <class ForwardIterator>
void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
Effects: Эквивалентен:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type();
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);
Effects: Как будто по:
for (; first != last; ++result, (void) ++first) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(*first);
template <class InputIterator, class Size, class ForwardIterator>
ForwardIterator uninitialized_copy_n(InputIterator first, Size n,
ForwardIterator result);
Effects: Как будто по:
for ( ; n > 0; ++result, (void) ++first, --n) { ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(*first); }
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_move(InputIterator first, InputIterator last,
ForwardIterator result);
Effects: Эквивалентен:
for (; first != last; (void)++result, ++first) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(std::move(*first)); return result;
Remarks: Если выбрасывается исключение, некоторые объекты в диапазоне [first, last) остаются в допустимом, но неуказанном состоянии.
template <class InputIterator, class Size, class ForwardIterator>
pair<InputIterator, ForwardIterator>
uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
Effects: Эквивалентен:
for (; n > 0; ++result, (void) ++first, --n) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(std::move(*first)); return {first,result};
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last,
const T& x);
Effects: Как будто по:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type(x);
template <class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
template <class T>
void destroy_at(T* location);
template <class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Size>
ForwardIterator destroy_n(ForwardIterator first, Size n);
void* aligned_alloc(size_t alignment, size_t size);
void* calloc(size_t nmemb, size_t size);
void* malloc(size_t size);
void* realloc(void* ptr, size_t size);
Remarks: Эти функции не пытаются выделить память с помощью вызова ::operator new() ([support.dynamic]).
Хранилище, выделенное непосредственно с помощью этих функций, неявно объявляется доступным (см. [basic.stc.dynamic.safety]) При выделении, перестает объявляться доступным при освобождении и не обязательно перестает объявляться доступным в результате undeclare_reachable() вызова. [ Note: Это позволяет существующим библиотекам C оставаться незатронутыми ограничениями на указатели, которые не извлекаются безопасно, за счет предоставления гораздо меньшего количества вариантов сборки мусора и обнаружения утечек для malloc()-распределенных объектов. Это также позволяет malloc() реализовать с отдельной ареной распределения, минуя обычную declare_reachable() реализацию. Вышеупомянутые функции никогда не должны преднамеренно использоваться в качестве замены declare_reachable(), и вновь написанный код настоятельно рекомендуется обрабатывать память, выделенную этими функциями, как если бы она была выделена с помощью operator new. ] — end note
void free(void* ptr);
См. Также: ISO C 7.22.3.