20 General utilities library [utilities]

20.11 Smart pointers [smartptr]

20.11.1 Class template unique_ptr [unique.ptr]

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

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;
    explicit unique_ptr(pointer p) noexcept;
    unique_ptr(pointer p, see below d1) noexcept;
    unique_ptr(pointer p, see below d2) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept
      : unique_ptr() { }
    template <class U, class E>
      unique_ptr(unique_ptr<U, E>&& u) noexcept;

    // [unique.ptr.single.dtor], destructor
    ~unique_ptr();

    // [unique.ptr.single.asgn], assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;

    // [unique.ptr.single.observers], observers
    add_lvalue_reference_t<T> operator*() const;
    pointer operator->() const noexcept;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;

    // [unique.ptr.single.modifiers], modifiers
    pointer release() noexcept;
    void reset(pointer p = pointer()) noexcept;
    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 satisfy the requirements of Destructible (Table [tab:destructible]).

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 satisfy the requirements of NullablePointer ([nullablepointer.requirements]).

Example: Given an allocator type X ([allocator.requirements]) 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.11.1.2.1 unique_ptr constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept;

Requires: D shall satisfy the requirements of DefaultConstructible (Table [tab:defaultconstructible]), and that construction shall 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.

Remarks: If this constructor is instantiated with a pointer type or reference type for the template argument D, the program is ill-formed.

explicit unique_ptr(pointer p) noexcept;

Requires: D shall satisfy the requirements of DefaultConstructible (Table [tab:defaultconstructible]), and that construction shall 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.

Remarks: If this constructor is instantiated with a pointer type or reference type for the template argument D, the program is ill-formed.

unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept;

The signature of these constructors depends upon whether D is a reference type. If D is a non-reference type A, then the signatures are:

unique_ptr(pointer p, const A& d);
unique_ptr(pointer p, A&& d);

If D is an lvalue reference type A&, then the signatures are:

unique_ptr(pointer p, A& d);
unique_ptr(pointer p, A&& d);

If D is an lvalue reference type const A&, then the signatures are:

unique_ptr(pointer p, const A& d);
unique_ptr(pointer p, const A&& d);

Requires:

  • If D is not an lvalue reference type then

    • If d is an lvalue or const rvalue then the first constructor of this pair will be selected. D shall satisfy the requirements of CopyConstructible (Table [tab:copyconstructible]), and the copy constructor of D shall not throw an exception. This unique_ptr will hold a copy of d.

    • Otherwise, d is a non-const rvalue and the second constructor of this pair will be selected. D shall satisfy the requirements of MoveConstructible (Table [tab:moveconstructible]), and the move constructor of D shall not throw an exception. This unique_ptr will hold a value move constructed from d.

  • Otherwise D is an lvalue reference type. d shall be reference-compatible with one of the constructors. If d is an rvalue, it will bind to the second constructor of this pair and the program is ill-formed. [ Note: The diagnostic could be implemented using a static_assert which assures that D is not a reference type.  — end note ] Else d is an lvalue and will bind to the first constructor of this pair. The type which D references need not be CopyConstructible nor MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d. [ Note: D may not be an rvalue reference type.  — end note ]

Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and initializing the deleter as described above.

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.

Example:

D d;
unique_ptr<int, D> p1(new int, D());        // D must be MoveConstructible
unique_ptr<int, D> p2(new int, d);          // D must be CopyConstructible
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 ]

unique_ptr(unique_ptr&& u) noexcept;

Requires: If D is not a reference type, D shall satisfy the requirements of MoveConstructible (Table [tab:moveconstructible]). Construction of the deleter from an rvalue of type D shall not throw an exception.

Effects: Constructs a unique_ptr by transferring ownership from u to *this. 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: The deleter constructor can be implemented with std::forward<D>.  — end note ]

Postconditions: get() yields the value u.get() yielded before the construction. 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> unique_ptr(unique_ptr<U, E>&& u) noexcept;

Requires: If E is not a reference type, construction of the deleter from an rvalue of type E shall be well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the deleter from an lvalue of type E shall be well formed and shall not throw an exception.

Remarks: This constructor shall not participate in overload resolution unless:

  • 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.

Effects: Constructs a unique_ptr by transferring ownership from u to *this. 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: The deleter constructor can be implemented with std::forward<E>.  — end note ]

Postconditions: get() yields the value u.get() yielded before the construction. get_deleter() returns a reference to the stored deleter that was constructed from u.get_deleter().

20.11.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]

~unique_ptr();

Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. [ Note: The use of default_delete requires T to be a complete type.  — end note ]

Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

20.11.1.2.3 unique_ptr assignment [unique.ptr.single.asgn]

unique_ptr& operator=(unique_ptr&& u) noexcept;

Requires: If D is not a reference type, D shall satisfy the requirements of MoveAssignable (Table [tab:moveassignable]) and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D is a reference type; remove_reference_t<D> shall satisfy the CopyAssignable requirements and assignment of the deleter from an lvalue of type D shall not throw an exception.

Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).

Returns: *this.

template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

Requires: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be well-formed and shall not throw an exception. Otherwise, E is a reference type and assignment of the deleter from an lvalue of type E shall be well-formed and shall not throw an exception.

Remarks: This operator shall not participate in overload resolution unless:

  • 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.

Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<E>(u.get_deleter()).

Returns: *this.

unique_ptr& operator=(nullptr_t) noexcept;

Effects: As if by reset().

Postconditions: get() == nullptr.

Returns: *this.

20.11.1.2.4 unique_ptr observers [unique.ptr.single.observers]

add_lvalue_reference_t<T> operator*() const;

Requires: get() != nullptr.

Returns: *get().

pointer operator->() const noexcept;

Requires: get() != nullptr.

Returns: get().

Note: use typically requires that T be a complete type.

pointer get() const noexcept;

Returns: The stored pointer.

deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept;

Returns: A reference to the stored deleter.

explicit operator bool() const noexcept;

Returns: get() != nullptr.

20.11.1.2.5 unique_ptr modifiers [unique.ptr.single.modifiers]

pointer release() noexcept;

Postconditions: get() == nullptr.

Returns: The value get() had at the start of the call to release.

void reset(pointer p = pointer()) noexcept;

Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions.

Effects: Assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not equal to nullptr, calls get_deleter()(old_p). [ Note: The order of these operations is significant because the call to get_deleter() may destroy *this.  — end note ]

Postconditions: get() == p. [ Note: The postcondition does not hold if the call to get_deleter() destroys *this since this->get() is no longer a valid expression.  — end note ]

void swap(unique_ptr& u) noexcept;

Requires: get_deleter() shall be swappable ([swappable.requirements]) and shall not throw an exception under swap.

Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.