20 General utilities library [utilities]

20.7 Memory [memory]

20.7.1 In general [memory.general]

This subclause describes the contents of the header <memory> ([memory.syn]) and some of the contents of the C headers <cstdlib> and <cstring> ([c.malloc]).

20.7.2 Header <memory> synopsis [memory.syn]

The header <memory> defines several types and function templates that describe properties of pointers and pointer-like types, manage memory for containers and other template types, and construct multiple objects in uninitialized memory buffers ([pointer.traits][specialized.algorithms]). The header also defines the templates unique_ptr, shared_ptr, weak_ptr, and various function templates that operate on objects of these types ([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(std::size_t alignment, std::size_t size,
    void*& ptr, std::size_t& space);

  // [allocator.tag], allocator argument tag
  struct allocator_arg_t { };
  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 allocator<void>;
  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;

  // [storage.iterator], raw storage iterator:
  template <class OutputIterator, class T> class raw_storage_iterator;

  // [temporary.buffer], temporary buffers:
  template <class T>
    pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;
  template <class T>
    void return_temporary_buffer(T* p);

  // [specialized.algorithms], specialized algorithms:
  template <class T> T* addressof(T& r) noexcept;
  template <class InputIterator, class ForwardIterator>
    ForwardIterator uninitialized_copy(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 ForwardIterator, class T>
    void uninitialized_fill(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);

  // [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.weakptr], 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==(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
  template<class T, class U>
    bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
  template<class T, class U>
    bool operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
  template<class T, class U>
    bool operator>(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
  template<class T, class U>
    bool operator<=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
  template<class T, class U>
    bool operator>=(shared_ptr<T> const& a, shared_ptr<U> const& 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(shared_ptr<U> const& r) noexcept;
  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept;
  template<class T, class U>
    shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept;

  // [util.smartptr.getdeleter], shared_ptr get_deleter:
  template<class D, class T> D* get_deleter(shared_ptr<T> const& 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, shared_ptr<Y> const& 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> class 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> >;

  // [depr.auto.ptr], auto_ptr (deprecated)
  template <class X> class auto_ptr;
}

20.7.3 Pointer traits [pointer.traits]

The class template pointer_traits supplies a uniform interface to certain attributes of pointer-like types.

namespace std {
  template <class Ptr> struct pointer_traits {
    typedef Ptr       pointer;
    typedef see below element_type;
    typedef see below difference_type;

    template <class U> using rebind = see below;

    static pointer pointer_to(see below r);
  };

  template <class T> struct pointer_traits<T*> {
    typedef T*        pointer;
    typedef T         element_type;
    typedef ptrdiff_t difference_type;

    template <class U> using rebind = U*;

    static pointer pointer_to(see below r) noexcept;
  };
}

20.7.3.1 Pointer traits member types [pointer.traits.types]

typedef see below element_type;

Type: Ptr::element_type if such a type exists; otherwise, T if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the specialization is ill-formed.

typedef see below difference_type;

Type: Ptr::difference_type if such a type exists; otherwise, std::ptrdiff_t.

template <class U> using rebind = see below;

Alias template: Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind is ill-formed.

20.7.3.2 Pointer traits member functions [pointer.traits.functions]

static pointer pointer_traits::pointer_to(see below r); static pointer pointer_traits<T*>::pointer_to(see below r) noexcept;

Remark: If element_type is (possibly cv-qualified) void, the type of r is unspecified; otherwise, it is element_type&.

Returns: The first member function returns a pointer to r obtained by calling Ptr::pointer_to(r) through which indirection is valid; an instantiation of this function is ill-formed if Ptr does not have a matching pointer_to static member function. The second member function returns std::addressof(r).

20.7.4 Pointer safety [util.dynamic.safety]

A complete object is declared reachable while the number of calls to declare_reachable with an argument referencing the object exceeds the number of calls to undeclare_reachable with an argument referencing the object.

void declare_reachable(void* p);

Requires: p shall be a safely-derived pointer ([basic.stc.dynamic.safety]) or a null pointer value.

Effects: If p is not null, the complete object referenced by p is subsequently declared reachable ([basic.stc.dynamic.safety]).

Throws: May throw std::bad_alloc if the system cannot allocate additional memory that may be required to track objects declared reachable.

template <class T> T* undeclare_reachable(T* p);

Requires: If p is not null, the complete object referenced by p shall have been previously declared reachable, and shall be live ([basic.life]) from the time of the call until the last undeclare_reachable(p) call on the object.

Returns: A safely derived copy of p which shall compare equal to p.

Throws: Nothing.

Note: It is expected that calls to declare_reachable(p) will consume a small amount of memory in addition to that occupied by the referenced object until the matching call to undeclare_reachable(p) is encountered. Long running programs should arrange that calls are matched.  — end note ]

void declare_no_pointers(char* p, size_t n);

Requires: No bytes in the specified range are currently registered with declare_no_pointers(). If the specified range is in an allocated object, then it must be entirely within a single allocated object. The object must be live until the corresponding undeclare_no_pointers() call. [ Note: In a garbage-collecting implementation, the fact that a region in an object is registered with declare_no_pointers() should not prevent the object from being collected.  — end note ]

Effects: The n bytes starting at p no longer contain traceable pointer locations, independent of their type. Hence indirection through a pointer located there is undefined if the object it points to was created by global operator new and not previously declared reachable. [ Note: This may be used to inform a garbage collector or leak detector that this region of memory need not be traced.  — end note ]

Throws: Nothing.

Note: Under some conditions implementations may need to allocate memory. However, the request can be ignored if memory allocation fails.  — end note ]

void undeclare_no_pointers(char* p, size_t n);

Requires: The same range must previously have been passed to declare_no_pointers().

Effects: Unregisters a range registered with declare_no_pointers() for destruction. It must be called before the lifetime of the object ends.

Throws: Nothing.

pointer_safety get_pointer_safety() noexcept;

Returns: pointer_safety::strict if the implementation has strict pointer safety ([basic.stc.dynamic.safety]). It is implementation defined whether get_pointer_safety returns pointer_safety::relaxed or pointer_safety::preferred if the implementation has relaxed pointer safety.230

pointer_safety::preferred might be returned to indicate that a leak detector is running so that the program can avoid spurious leak reports.

20.7.5 Align [ptr.align]

void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space);

Effects: If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to by ptr with length space, the function updates ptr to point to the first possible address of such storage and decreases space by the number of bytes used for alignment. Otherwise, the function does nothing.

Requires:

  • alignment shall be a fundamental alignment value or an extended alignment value supported by the implementation in this context

  • ptr shall point to contiguous storage of at least space bytes

Returns: A null pointer if the requested aligned buffer would not fit into the available space, otherwise the adjusted value of ptr.

Note: The function updates its ptr and space arguments so that it can be called repeatedly with possibly different alignment and size arguments for the same buffer.  — end note ]

20.7.6 Allocator argument tag [allocator.tag]

namespace std { struct allocator_arg_t { }; constexpr allocator_arg_t allocator_arg{}; }

The allocator_arg_t struct is an empty structure type used as a unique type to disambiguate constructor and function overloading. Specifically, several types (see tuple [tuple]) have constructors with allocator_arg_t as the first argument, immediately followed by an argument of a type that satisfies the Allocator requirements ([allocator.requirements]).

20.7.7 uses_allocator [allocator.uses]

20.7.7.1 uses_allocator trait [allocator.uses.trait]

template <class T, class Alloc> struct uses_allocator;

Remark: automatically detects whether T has a nested allocator_type that is convertible from Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts]). The implementation shall provide a definition that is derived from true_type if a type T::allocator_type exists and is_convertible<Alloc, T::allocator_type>::value != false, otherwise it shall be derived from false_type. A program may specialize this template to derive from true_type for a user-defined type T that does not have a nested allocator_type but nonetheless can be constructed with an allocator where either:

  • the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or

  • the last argument of a constructor has type Alloc.

20.7.7.2 uses-allocator construction [allocator.uses.construction]

Uses-allocator construction with allocator Alloc refers to the construction of an object obj of type T, using constructor arguments v1, v2, ..., vN of types V1, V2, ..., VN, respectively, and an allocator alloc of type Alloc, according to the following rules:

  • if uses_allocator<T, Alloc>::value is false and is_constructible<T, V1, V2, ..., VN>::value is true, then obj is initialized as obj(v1, v2, ..., vN);

  • otherwise, if uses_allocator<T, Alloc>::value is true and is_constructible<T, allocator_arg_t, Alloc, V1, V2, ..., VN>::value is true, then obj is initialized as obj(allocator_arg, alloc, v1, v2, ..., vN);

  • otherwise, if uses_allocator<T, Alloc>::value is true and is_constructible<T, V1, V2, ..., VN, Alloc>::value is true, then obj is initialized as obj(v1, v2, ..., vN, alloc);

  • otherwise, the request for uses-allocator construction is ill-formed. [ Note: An error will result if uses_allocator<T, Alloc>::value is true but the specific constructor does not take an allocator. This definition prevents a silent failure to pass the allocator to an element.  — end note ]

20.7.8 Allocator traits [allocator.traits]

The class template allocator_traits supplies a uniform interface to all allocator types. An allocator cannot be a non-class type, however, even if allocator_traits supplies the entire required interface. [ Note: Thus, it is always possible to create a derived class from an allocator.  — end note ]

namespace std {
  template <class Alloc> struct allocator_traits {
    typedef Alloc allocator_type;

    typedef typename Alloc::value_type value_type;

    typedef see below pointer;
    typedef see below const_pointer;
    typedef see below void_pointer;
    typedef see below const_void_pointer;

    typedef see below difference_type;
    typedef see below size_type;

    typedef see below propagate_on_container_copy_assignment;
    typedef see below propagate_on_container_move_assignment;
    typedef see below propagate_on_container_swap;

    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);
  };
}

20.7.8.1 Allocator traits member types [allocator.traits.types]

typedef see below pointer;

Type: Alloc::pointer if such a type exists; otherwise, value_type*.

typedef see below const_pointer;

Type: Alloc::const_pointer if such a type exists; otherwise, pointer_traits<pointer>::rebind<const value_type>.

typedef see below void_pointer;

Type: Alloc::void_pointer if such a type exists; otherwise, pointer_traits<pointer>::rebind<void>.

typedef see below const_void_pointer;

Type: Alloc::const_void_pointer if such a type exists; otherwise, pointer_traits<pointer>::rebind<const void>.

typedef see below difference_type;

Type: Alloc::difference_type if such a type exists; otherwise, pointer_traits<pointer>::difference_type.

typedef see below size_type;

Type: Alloc::size_type if such a type exists; otherwise, make_unsigned_t<difference_type>.

typedef see below propagate_on_container_copy_assignment;

Type: Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise false_type.

typedef see below propagate_on_container_move_assignment;

Type: Alloc::propagate_on_container_move_assignment if such a type exists, otherwise false_type.

typedef see below propagate_on_container_swap;

Type: Alloc::propagate_on_container_swap if such a type exists, otherwise false_type.

template <class T> using rebind_alloc = see below;

Alias template: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args> if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind_alloc is ill-formed.

20.7.8.2 Allocator traits static member functions [allocator.traits.members]

static pointer allocate(Alloc& a, size_type n);

Returns: a.allocate(n).

static pointer allocate(Alloc& a, size_type n, const_void_pointer hint);

Returns: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n).

static void deallocate(Alloc& a, pointer p, size_type n);

Effects: calls a.deallocate(p, n).

Throws: Nothing.

template <class T, class... Args> static void construct(Alloc& a, T* p, Args&&... args);

Effects: calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed; otherwise, invokes ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).

template <class T> static void destroy(Alloc& a, T* p);

Effects: calls a.destroy(p) if that call is well-formed; otherwise, invokes p->~T().

static size_type max_size(const Alloc& a) noexcept;

Returns: a.max_size() if that expression is well-formed; otherwise, numeric_limits<size_type>::max().

static Alloc select_on_container_copy_construction(const Alloc& rhs);

Returns: rhs.select_on_container_copy_construction() if that expression is well-formed; otherwise, rhs.

20.7.9 The default allocator [default.allocator]

namespace std {
  template <class T> class allocator;

  // specialize for void:
  template <> class allocator<void> {
  public:
    typedef void*   pointer;
    typedef const void* const_pointer;
    // reference-to-void members are impossible.
    typedef void  value_type;
    template <class U> struct rebind { typedef allocator<U> other; };
  };

  template <class T> class allocator {
   public:
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;
    typedef T         value_type;
    template <class U> struct rebind { typedef allocator<U> other; };
    typedef true_type propagate_on_container_move_assignment;
    
    allocator() noexcept;
    allocator(const allocator&) noexcept;
    template <class U> allocator(const allocator<U>&) noexcept;
   ~allocator();

    pointer address(reference x) const noexcept;
    const_pointer address(const_reference x) const noexcept;

    pointer allocate(
      size_type, allocator<void>::const_pointer hint = 0);
    void deallocate(pointer p, size_type n);
    size_type max_size() const noexcept;

    template<class U, class... Args>
      void construct(U* p, Args&&... args);
    template <class U>
      void destroy(U* p);
  };
}

20.7.9.1 allocator members [allocator.members]

Except for the destructor, member functions of the default allocator shall not introduce data races ([intro.multithread]) as a result of concurrent calls to those member functions from different threads. Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen before the next allocation (if any) in this order.

pointer address(reference x) const noexcept;

Returns: The actual address of the object referenced by x, even in the presence of an overloaded operator&.

const_pointer address(const_reference x) const noexcept;

Returns: The actual address of the object referenced by x, even in the presence of an overloaded operator&.

pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);

Note: In a container member function, the address of an adjacent element is often a good choice to pass for the hint argument.  — end note ]

Returns: A pointer to the initial element of an array of storage of size n * sizeof(T), aligned appropriately for objects of type T. It is implementation-defined whether over-aligned types are supported ([basic.align]).

Remark: the storage is obtained by calling ::operator new(std::size_t) ([new.delete]), but it is unspecified when or how often this function is called. The use of hint is unspecified, but intended as an aid to locality if an implementation so desires.

Throws: bad_alloc if the storage cannot be obtained.

void deallocate(pointer p, size_type n);

Requires: p shall be a pointer value obtained from allocate(). n shall equal the value passed as the first argument to the invocation of allocate which returned p.

Effects: Deallocates the storage referenced by p .

Remarks: Uses ::operator delete(void*, std::size_t) ([new.delete]), but it is unspecified when this function is called.

size_type max_size() const noexcept;

Returns: The largest value N for which the call allocate(N,0) might succeed.

template <class U, class... Args> void construct(U* p, Args&&... args);

Effects: ::new((void *)p) U(std::forward<Args>(args)...)

template <class U> void destroy(U* p);

Effects: p->~U()

20.7.9.2 allocator globals [allocator.globals]

template <class T1, class T2> bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept;

Returns: true.

template <class T1, class T2> bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept;

Returns: false.

20.7.10 Raw storage iterator [storage.iterator]

raw_storage_iterator is provided to enable algorithms to store their results into uninitialized memory. The template parameter OutputIterator is required to have its operator* return an object for which operator& is defined and returns a pointer to T, and is also required to satisfy the requirements of an output iterator ([output.iterators]).

namespace std {
  template <class OutputIterator, class T>
  class raw_storage_iterator
    : public iterator<output_iterator_tag,void,void,void,void> {
  public:
    explicit raw_storage_iterator(OutputIterator x);

    raw_storage_iterator& operator*();
    raw_storage_iterator& operator=(const T& element);
    raw_storage_iterator& operator++();
    raw_storage_iterator  operator++(int);
  };
}

explicit raw_storage_iterator(OutputIterator x);

Effects: Initializes the iterator to point to the same value to which x points.

raw_storage_iterator& operator*();

Returns: *this

raw_storage_iterator& operator=(const T& element);

Effects: Constructs a value from element at the location to which the iterator points.

Returns: A reference to the iterator.

raw_storage_iterator& operator++();

Effects: Pre-increment: advances the iterator and returns a reference to the updated iterator.

raw_storage_iterator operator++(int);

Effects: Post-increment: advances the iterator and returns the old value of the iterator.

20.7.11 Temporary buffers [temporary.buffer]

template <class T> pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;

Effects: Obtains a pointer to storage sufficient to store up to n adjacent T objects. It is implementation-defined whether over-aligned types are supported ([basic.align]).

Returns: A pair containing the buffer's address and capacity (in the units of sizeof(T)), or a pair of 0 values if no storage can be obtained or if n <= 0.

template <class T> void return_temporary_buffer(T* p);

Effects: Deallocates the buffer to which p points.

Requires: The buffer shall have been previously allocated by get_temporary_buffer.

20.7.12 Specialized algorithms [specialized.algorithms]

All the iterators that are used as template parameters in the following algorithms are required to have their operator* return an object for which operator& is defined and returns a pointer to T. In the algorithm uninitialized_copy, the template parameter InputIterator is required to satisfy the requirements of an input iterator ([input.iterators]). In all of the following algorithms, the template parameter ForwardIterator is required to satisfy the requirements of a forward iterator ([forward.iterators]), and is required to have the property that no exceptions are thrown from increment, assignment, comparison, or indirection through valid iterators. In the following algorithms, if an exception is thrown there are no effects.

20.7.12.1 addressof [specialized.addressof]

template <class T> T* addressof(T& r) noexcept;

Returns: The actual address of the object or function referenced by r, even in the presence of an overloaded operator&.

20.7.12.2 uninitialized_copy [uninitialized.copy]

template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);

Effects:

for (; first != last; ++result, ++first)
  ::new (static_cast<void*>(&*result))
    typename iterator_traits<ForwardIterator>::value_type(*first);

Returns: result

template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result);

Effects:

for ( ; n > 0; ++result, ++first, --n) {
  ::new (static_cast<void*>(&*result))
    typename iterator_traits<ForwardIterator>::value_type(*first);
}

Returns: result

20.7.12.3 uninitialized_fill [uninitialized.fill]

template <class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);

Effects:

for (; first != last; ++first)
  ::new (static_cast<void*>(&*first))
    typename iterator_traits<ForwardIterator>::value_type(x);

20.7.12.4 uninitialized_fill_n [uninitialized.fill.n]

template <class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);

Effects:

for (; n--; ++first)
  ::new (static_cast<void*>(&*first))
    typename iterator_traits<ForwardIterator>::value_type(x);
return first;

20.7.13 C library [c.malloc]

Table [tab:util.hdr.cstdlib] describes the header <cstdlib>.

Table 45 — Header <cstdlib> synopsis
TypeName(s)
Functions: calloc malloc
free realloc

The contents are the same as the Standard C library header <stdlib.h>, with the following changes:

The functions calloc(), malloc(), and realloc() do not attempt to allocate storage by calling ::operator new() ([support.dynamic]).

The function free() does not attempt to deallocate storage by calling ::operator delete().

See also: ISO C Clause 7.11.2.

Storage allocated directly with malloc(), calloc(), or realloc() is implicitly declared reachable (see [basic.stc.dynamic.safety]) on allocation, ceases to be declared reachable on deallocation, and need not cease to be declared reachable as the result of an undeclare_reachable() call. [ Note: This allows existing C libraries to remain unaffected by restrictions on pointers that are not safely derived, at the expense of providing far fewer garbage collection and leak detection options for malloc()-allocated objects. It also allows malloc() to be implemented with a separate allocation arena, bypassing the normal declare_reachable() implementation. The above functions should never intentionally be used as a replacement for declare_reachable(), and newly written code is strongly encouraged to treat memory allocated with these functions as though it were allocated with operator new.  — end note ]

Table [tab:util.hdr.cstring] describes the header <cstring>.

Table 46 — Header <cstring> synopsis
TypeName(s)
Macro: NULL
Type: size_t
Functions: memchr memcmp
memcpy memmove memset

The contents are the same as the Standard C library header <string.h>, with the change to memchr() specified in [c.strings].

See also: ISO C Clause 7.11.2.