20 Memory management library [mem]

20.3 Smart pointers [smartptr]

20.3.1 Unique-ownership pointers [unique.ptr]

20.3.1.1 General [unique.ptr.general]

A unique pointer is an object that owns another object and manages that other object through a pointer.
More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of p when u is itself destroyed (e.g., when leaving block scope ([stmt.dcl])).
In this context, u is said to own p.
The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct invocation results in p's appropriate disposition (typically its deletion).
Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter.
Upon request, u can reset (replace) u.p and u.d with another pointer and deleter, but properly disposes of its owned object via the associated deleter before such replacement is considered completed.
Each object of a type U instantiated from the unique_ptr template specified in [unique.ptr] has the strict ownership semantics, specified above, of a unique pointer.
In partial satisfaction of these semantics, each such U is Cpp17MoveConstructible and Cpp17MoveAssignable, but is not Cpp17CopyConstructible nor Cpp17CopyAssignable.
The template parameter T of unique_ptr may be an incomplete type.
[Note 1: 
The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from a function.
— end note]

20.3.1.2 Default deleters [unique.ptr.dltr]

20.3.1.2.1 In general [unique.ptr.dltr.general]

The class template default_delete serves as the default deleter (destruction policy) for the class template unique_ptr.
The template parameter T of default_delete may be an incomplete type.

20.3.1.2.2 default_delete [unique.ptr.dltr.dflt]

namespace std { template<class T> struct default_delete { constexpr default_delete() noexcept = default; template<class U> constexpr default_delete(const default_delete<U>&) noexcept; constexpr void operator()(T*) const; }; }
template<class U> constexpr default_delete(const default_delete<U>& other) noexcept;
Constraints: U* is implicitly convertible to T*.
Effects: Constructs a default_delete object from another default_delete<U> object.
constexpr void operator()(T* ptr) const;
Mandates: T is a complete type.
Effects: Calls delete on ptr.

20.3.1.2.3 default_delete<T[]> [unique.ptr.dltr.dflt1]

namespace std { template<class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default; template<class U> constexpr default_delete(const default_delete<U[]>&) noexcept; template<class U> constexpr void operator()(U* ptr) const; }; }
template<class U> constexpr default_delete(const default_delete<U[]>& other) noexcept;
Constraints: U(*)[] is convertible to T(*)[].
Effects: Constructs a default_delete object from another default_delete<U[]> object.
template<class U> constexpr void operator()(U* ptr) const;
Constraints: U(*)[] is convertible to T(*)[].
Mandates: U is a complete type.
Effects: Calls delete[] on ptr.

20.3.1.3 unique_ptr for single objects [unique.ptr.single]

20.3.1.3.1 General [unique.ptr.single.general]

namespace std { template<class T, class D = default_delete<T>> class unique_ptr { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.single.ctor], constructors constexpr unique_ptr() noexcept; constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, see below d1) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, see below d2) noexcept; constexpr unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept; // [unique.ptr.single.dtor], destructor constexpr ~unique_ptr(); // [unique.ptr.single.asgn], assignment constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.single.observers], observers constexpr add_lvalue_reference_t<T> operator*() const noexcept(see below); constexpr pointer operator->() const noexcept; constexpr pointer get() const noexcept; constexpr deleter_type& get_deleter() noexcept; constexpr const deleter_type& get_deleter() const noexcept; constexpr explicit operator bool() const noexcept; // [unique.ptr.single.modifiers], modifiers constexpr pointer release() noexcept; constexpr void reset(pointer p = pointer()) noexcept; constexpr void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
The default type for the template parameter D is default_delete.
A client-supplied template argument D shall be a function object type ([function.objects]), lvalue reference to function, or lvalue reference to function object type for which, given a value d of type D and a value ptr of type unique_ptr<T, D>​::​pointer, the expression d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
If the deleter's type D is not a reference type, D shall meet the Cpp17Destructible requirements (Table 35).
If the qualified-id remove_reference_t<D>​::​pointer is valid and denotes a type ([temp.deduct]), then unique_ptr<T, D>​::​pointer shall be a synonym for remove_reference_t<D>​::​pointer.
Otherwise unique_ptr<T, D>​::​pointer shall be a synonym for element_type*.
The type unique_ptr<T, D>​::​pointer shall meet the Cpp17NullablePointer requirements (Table 36).
[Example 1: 
Given an allocator type X ([allocator.requirements.general]) and letting A be a synonym for allocator_traits<X>, the types A​::​pointer, A​::​const_pointer, A​::​void_pointer, and A​::​const_void_pointer may be used as unique_ptr<T, D>​::​pointer.
— end example]

20.3.1.3.2 Constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept; constexpr unique_ptr(nullptr_t) noexcept;
Constraints: is_pointer_v<deleter_type> is false and is_default_constructible_v<deleter_type> is true.
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 30), and that construction does not throw an exception.
Effects: Constructs a unique_ptr object that owns nothing, value-initializing the stored pointer and the stored deleter.
Postconditions: get() == nullptr.
get_deleter() returns a reference to the stored deleter.
constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;
Constraints: is_pointer_v<deleter_type> is false and is_default_constructible_v<deleter_type> is true.
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 30), and that construction does not throw an exception.
Effects: Constructs a unique_ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter.
Postconditions: get() == p.
get_deleter() returns a reference to the stored deleter.
constexpr unique_ptr(type_identity_t<pointer> p, const D& d) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, remove_reference_t<D>&& d) noexcept;
Constraints: is_constructible_v<D, decltype(d)> is true.
Preconditions: For the first constructor, if D is not a reference type, D meets the Cpp17CopyConstructible requirements and such construction does not exit via an exception.
For the second constructor, if D is not a reference type, D meets the Cpp17MoveConstructible requirements and such construction does not exit via an exception.
Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and initializing the deleter from std​::​forward<decltype(d)>(d).
Postconditions: get() == p.
get_deleter() returns a reference to the stored deleter.
If D is a reference type then get_deleter() returns a reference to the lvalue d.
Remarks: If D is a reference type, the second constructor is defined as deleted.
[Example 1: D d; unique_ptr<int, D> p1(new int, D()); // D must be Cpp17MoveConstructible unique_ptr<int, D> p2(new int, d); // D must be Cpp17CopyConstructible unique_ptr<int, D&> p3(new int, d); // p3 holds a reference to d unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined // with reference deleter type — end example]
constexpr unique_ptr(unique_ptr&& u) noexcept;
Constraints: is_move_constructible_v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveConstructible requirements (Table 31).
Construction of the deleter from an rvalue of type D does not throw an exception.
Effects: Constructs a unique_ptr from u.
If D is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
[Note 1: 
The construction of the deleter can be implemented with std​::​forward<D>.
— end note]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_deleter() returns a reference to the stored deleter that was constructed from u.get_deleter().
If D is a reference type then get_deleter() and u.get_deleter() both reference the same lvalue deleter.
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_ptr<U, E>​::​pointer is implicitly convertible to pointer,
  • U is not an array type, and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
Preconditions: If E is not a reference type, construction of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and construction of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Constructs a unique_ptr from u.
If E is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
[Note 2: 
The deleter constructor can be implemented with std​::​forward<E>.
— end note]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_deleter() returns a reference to the stored deleter that was constructed from u.get_deleter().

20.3.1.3.3 Destructor [unique.ptr.single.dtor]

constexpr ~unique_ptr();
Effects: Equivalent to: if (get()) get_deleter()(get());
[Note 1: 
The use of default_delete requires T to be a complete type.
— end note]
Remarks: The behavior is undefined if the evaluation of get_deleter()(get()) throws an exception.

20.3.1.3.4 Assignment [unique.ptr.single.asgn]

constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
Constraints: is_move_assignable_v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveAssignable requirements (Table 33) and assignment of the deleter from an rvalue of type D does not throw an exception.
Otherwise, D is a reference type; remove_reference_t<D> meets the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of type D does not throw an exception.
Effects: Calls reset(u.release()) followed by get_deleter() = std​::​forward<D>(u.get_deleter()).
Postconditions: If this != addressof(u), u.get() == nullptr, otherwise u.get() is unchanged.
Returns: *this.
template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_ptr<U, E>​::​pointer is implicitly convertible to pointer, and
  • U is not an array type, and
  • is_assignable_v<D&, E&&> is true.
Preconditions: If E is not a reference type, assignment of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and assignment of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Calls reset(u.release()) followed by get_deleter() = std​::​forward<E>(u.get_deleter()).
Postconditions: u.get() == nullptr.
Returns: *this.
constexpr unique_ptr& operator=(nullptr_t) noexcept;
Effects: As if by reset().
Postconditions: get() == nullptr.
Returns: *this.

20.3.1.3.5 Observers [unique.ptr.single.observers]

constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));
Preconditions: get() != nullptr.
Returns: *get().
constexpr pointer operator->() const noexcept;
Preconditions: get() != nullptr.
Returns: get().
[Note 1: 
The use of this function typically requires that T be a complete type.
— end note]
constexpr pointer get() const noexcept;
Returns: The stored pointer.
constexpr deleter_type& get_deleter() noexcept; constexpr const deleter_type& get_deleter() const noexcept;
Returns: A reference to the stored deleter.
constexpr explicit operator bool() const noexcept;
Returns: get() != nullptr.

20.3.1.3.6 Modifiers [unique.ptr.single.modifiers]

constexpr pointer release() noexcept;
Postconditions: get() == nullptr.
Returns: The value get() had at the start of the call to release.
constexpr void reset(pointer p = pointer()) noexcept;
Effects: Assigns p to the stored pointer, and then, with the old value of the stored pointer, old_p, evaluates if (old_p) get_deleter()(old_p);
[Note 1: 
The order of these operations is significant because the call to get_deleter() might destroy *this.
— end note]
Postconditions: get() == p.
[Note 2: 
The postcondition does not hold if the call to get_deleter() destroys *this since this->get() is no longer a valid expression.
— end note]
Remarks: The behavior is undefined if the evaluation of get_deleter()(old_p) throws an exception.
constexpr void swap(unique_ptr& u) noexcept;
Preconditions: get_deleter() is swappable ([swappable.requirements]) and does not throw an exception under swap.
Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.

20.3.1.4 unique_ptr for array objects with a runtime length [unique.ptr.runtime]

20.3.1.4.1 General [unique.ptr.runtime.general]

namespace std { template<class T, class D> class unique_ptr<T[], D> { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.runtime.ctor], constructors constexpr unique_ptr() noexcept; template<class U> constexpr explicit unique_ptr(U p) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept; constexpr unique_ptr(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; // destructor constexpr ~unique_ptr(); // assignment constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.runtime.observers], observers constexpr T& operator[](size_t i) const; constexpr pointer get() const noexcept; constexpr deleter_type& get_deleter() noexcept; constexpr const deleter_type& get_deleter() const noexcept; constexpr explicit operator bool() const noexcept; // [unique.ptr.runtime.modifiers], modifiers constexpr pointer release() noexcept; template<class U> constexpr void reset(U p) noexcept; constexpr void reset(nullptr_t = nullptr) noexcept; constexpr void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
A specialization for array types is provided with a slightly altered interface.
  • Conversions between different types of unique_ptr<T[], D> that would be disallowed for the corresponding pointer-to-array types, and conversions to or from the non-array forms of unique_ptr, produce an ill-formed program.
  • Pointers to types derived from T are rejected by the constructors, and by reset.
  • The observers operator* and operator-> are not provided.
  • The indexing observer operator[] is provided.
  • The default deleter will call delete[].
Descriptions are provided below only for members that differ from the primary template.
The template argument T shall be a complete type.

20.3.1.4.2 Constructors [unique.ptr.runtime.ctor]

template<class U> constexpr explicit unique_ptr(U p) noexcept;
This constructor behaves the same as the constructor in the primary template that takes a single parameter of type pointer.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].
template<class U> constexpr unique_ptr(U p, see below d) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept;
These constructors behave the same as the constructors in the primary template that take a parameter of type pointer and a second parameter.
Constraints:
  • U is the same type as pointer,
  • U is nullptr_t, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
This constructor behaves the same as in the primary template.
Constraints: Where UP is unique_ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_type*, and
  • UP​::​pointer is the same type as UP​::​element_type*, and
  • UP​::​element_type(*)[] is convertible to element_type(*)[], and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
[Note 1: 
This replaces the Constraints: specification of the primary template.
— end note]

20.3.1.4.3 Assignment [unique.ptr.runtime.asgn]

template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
This operator behaves the same as in the primary template.
Constraints: Where UP is unique_ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_type*, and
  • UP​::​pointer is the same type as UP​::​element_type*, and
  • UP​::​element_type(*)[] is convertible to element_type(*)[], and
  • is_assignable_v<D&, E&&> is true.
[Note 1: 
This replaces the Constraints: specification of the primary template.
— end note]

20.3.1.4.4 Observers [unique.ptr.runtime.observers]

constexpr T& operator[](size_t i) const;
Preconditions: i < the number of elements in the array to which the stored pointer points.
Returns: get()[i].

20.3.1.4.5 Modifiers [unique.ptr.runtime.modifiers]

constexpr void reset(nullptr_t p = nullptr) noexcept;
Effects: Equivalent to reset(pointer()).
template<class U> constexpr void reset(U p) noexcept;
This function behaves the same as the reset member of the primary template.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].

20.3.1.5 Creation [unique.ptr.create]

template<class T, class... Args> constexpr unique_ptr<T> make_unique(Args&&... args);
Constraints: T is not an array type.
Returns: unique_ptr<T>(new T(std​::​forward<Args>(args)...)).
template<class T> constexpr unique_ptr<T> make_unique(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_ptr<T>(new remove_extent_t<T>[n]()).
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
Constraints: T is an array of known bound.
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite();
Constraints: T is not an array type.
Returns: unique_ptr<T>(new T).
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_ptr<T>(new remove_extent_t<T>[n]).
template<class T, class... Args> unspecified make_unique_for_overwrite(Args&&...) = delete;
Constraints: T is an array of known bound.

20.3.1.6 Specialized algorithms [unique.ptr.special]

template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Constraints: is_swappable_v<D> is true.
Effects: Calls x.swap(y).
template<class T1, class D1, class T2, class D2> constexpr bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: x.get() == y.get().
template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Let CT denote common_type_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>
Mandates:
  • unique_ptr<T1, D1>​::​pointer is implicitly convertible to CT and
  • unique_ptr<T2, D2>​::​pointer is implicitly convertible to CT.
Preconditions: The specialization less<CT> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: less<CT>()(x.get(), y.get()).
template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: y < x.
template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(y < x).
template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(x < y).
template<class T1, class D1, class T2, class D2> requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: compare_three_way()(x.get(), y.get()).
template<class T, class D> constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
Returns: !x.
template<class T, class D> constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Preconditions: The specialization less<unique_ptr<T, D>​::​pointer> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: The first function template returns less<unique_ptr<T, D>::pointer>()(x.get(), nullptr)
The second function template returns less<unique_ptr<T, D>::pointer>()(nullptr, x.get())
template<class T, class D> constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns nullptr < x.
The second function template returns x < nullptr.
template<class T, class D> constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(nullptr < x).
The second function template returns !(x < nullptr).
template<class T, class D> constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(x < nullptr).
The second function template returns !(nullptr < x).
template<class T, class D> requires three_way_comparable<typename unique_ptr<T, D>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer> operator<=>(const unique_ptr<T, D>& x, nullptr_t);
Returns: compare_three_way()(x.get(), static_cast<typename unique_ptr<T, D>::pointer>(nullptr)).

20.3.1.7 I/O [unique.ptr.io]

template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p);
Constraints: os << p.get() is a valid expression.
Effects: Equivalent to: os << p.get();
Returns: os.