The shared_ptr class template stores a pointer, usually obtained via new. shared_ptr implements semantics of shared ownership; the last remaining owner of the pointer is responsible for destroying the object, or otherwise releasing the resources associated with the stored pointer. A shared_ptr is said to be empty if it does not own a pointer.
namespace std { template<class T> class shared_ptr { public: using element_type = remove_extent_t<T>; using weak_type = weak_ptr<T>; // [util.smartptr.shared.const], constructors constexpr shared_ptr() noexcept; template<class Y> explicit shared_ptr(Y* p); template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a); template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept; shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept; template<class Y> explicit shared_ptr(const weak_ptr<Y>& r); template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } // [util.smartptr.shared.dest], destructor ~shared_ptr(); // [util.smartptr.shared.assign], assignment shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept; template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r); // [util.smartptr.shared.mod], modifiers void swap(shared_ptr& r) noexcept; void reset() noexcept; template<class Y> void reset(Y* p); template<class Y, class D> void reset(Y* p, D d); template<class Y, class D, class A> void reset(Y* p, D d, A a); // [util.smartptr.shared.obs], observers element_type* get() const noexcept; T& operator*() const noexcept; T* operator->() const noexcept; element_type& operator[](ptrdiff_t i) const; long use_count() const noexcept; explicit operator bool() const noexcept; template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept; }; template<class T> shared_ptr(weak_ptr<T>) -> shared_ptr<T>; template<class T, class D> shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>; // [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>& a, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& b) 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; template<class T, class U> shared_ptr<T> reinterpret_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); }
Specializations of shared_ptr shall be CopyConstructible, CopyAssignable, and LessThanComparable, allowing their use in standard containers. Specializations of shared_ptr shall be contextually convertible to bool, allowing their use in boolean expressions and declarations in conditions. The template parameter T of shared_ptr may be an incomplete type.
[ Example:
if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {
// do something with px
}
— end example ]
For purposes of determining the presence of a data race, member functions shall access and modify only the shared_ptr and weak_ptr objects themselves and not objects they refer to. Changes in use_count() do not reflect modifications that can introduce data races.
For the purposes of subclause [util.smartptr], a pointer type Y* is said to be compatible with a pointer type T* when either Y* is convertible to T* or Y is U[N] and T is cv U[].
In the constructor definitions below, enables shared_from_this with p, for a pointer p of type Y*, means that if Y has an unambiguous and accessible base class that is a specialization of enable_shared_from_this, then remove_cv_t<Y>* shall be implicitly convertible to T* and the constructor evaluates the statement:
if (p != nullptr && p->weak_this.expired()) p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));
The assignment to the weak_this member is not atomic and conflicts with any potentially concurrent access to the same object ([intro.multithread]).
constexpr shared_ptr() noexcept;
template<class Y> explicit shared_ptr(Y* p);
Requires: Y shall be a complete type. The expression delete[] p, when T is an array type, or delete p, when T is not an array type, shall have well-defined behavior, and shall not throw exceptions.
Effects: When T is not an array type, constructs a shared_ptr object that owns the pointer p. Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] p. When T is not an array type, enables shared_from_this with p. If an exception is thrown, delete p is called when T is not an array type, delete[] p otherwise.
Remarks: When T is an array type, this constructor shall not participate in overload resolution unless the expression delete[] p is well-formed and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*. When T is not an array type, this constructor shall not participate in overload resolution unless the expression delete p is well-formed and Y* is convertible to T*.
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
Requires: Construction of d and a deleter of type D initialized with std::move(d) shall not throw exceptions. The expression d(p) shall have well-defined behavior and shall not throw exceptions. A shall be an allocator ([allocator.requirements]).
Effects: Constructs a shared_ptr object that owns the object p and the deleter d. When T is not an array type, the first and second constructors enable shared_from_this with p. The second and fourth constructors shall use a copy of a to allocate memory for internal use. If an exception is thrown, d(p) is called.
Remarks: When T is an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*. When T is not an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and Y* is convertible to T*.
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
[ Note: To avoid the possibility of a dangling pointer, the user of this constructor must ensure that p remains valid at least until the ownership group of r is destroyed. — end note ]
[ Note: This constructor allows creation of an empty shared_ptr instance with a non-null stored pointer. — end note ]
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.
Effects: If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r.
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
Effects: Constructs a shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r. If an exception is thrown, the constructor has no effect.
Remarks: This constructor shall not participate in overload resolution unless Y* is compatible with T*.
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Remarks: This constructor shall not participate in overload resolution unless Y* is compatible with T* and unique_ptr<Y, D>::pointer is convertible to element_type*.
shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
[ Note: The use count updates caused by the temporary object construction and destruction are not observable side effects, so the implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary. In particular, in the example:
shared_ptr<int> p(new int); shared_ptr<void> q(p); p = p; q = p;
both assignments may be no-ops. — end note ]
shared_ptr& operator=(shared_ptr&& r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
void swap(shared_ptr& r) noexcept;
void reset() noexcept;
template<class Y> void reset(Y* p);
template<class Y, class D> void reset(Y* p, D d);
template<class Y, class D, class A> void reset(Y* p, D d, A a);
element_type* get() const noexcept;
T& operator*() const noexcept;
Remarks: When T is an array type or cv void, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
T* operator->() const noexcept;
Remarks: When T is an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
element_type& operator[](ptrdiff_t i) const;
Remarks: When T is not an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
long use_count() const noexcept;
Returns: The number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.
[ Note: When multiple threads can affect the return value of use_count(), the result should be treated as approximate. In particular, use_count() == 1 does not imply that accesses through a previously destroyed shared_ptr have in any sense completed. — end note ]
explicit operator bool() const noexcept;
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept;
template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
x.owner_before(y) defines a strict weak ordering as defined in [alg.sorting];
under the equivalence relation defined by owner_before, !a.owner_before(b) && !b.owner_before(a), two shared_ptr or weak_ptr instances are equivalent if and only if they share ownership or are both empty.
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);
Effects: Allocates memory suitable for an object of type T and constructs an object in that memory via the placement new-expression ::new (pv) T(std::forward<Args>(args)...). The template allocate_shared uses a copy of a to allocate memory. If an exception is thrown, the functions have no effect.
Returns: A shared_ptr instance that stores and owns the address of the newly constructed object of type T.
Remarks: The shared_ptr constructor called by this function enables shared_from_this with the address of the newly constructed object of type T. Implementations should perform no more than one memory allocation. [ Note: This provides efficiency equivalent to an intrusive smart pointer. — end note ]
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;
[ Note: Defining a comparison function allows shared_ptr objects to be used as keys in associative containers. — end note ]
template <class T>
bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator==(nullptr_t, const shared_ptr<T>& a) noexcept;
template <class T>
bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator!=(nullptr_t, const shared_ptr<T>& a) noexcept;
template <class T>
bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator<(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns less<shared_ptr<T>::element_type*>()(a.get(), nullptr). The second function template returns less<shared_ptr<T>::element_type*>()(nullptr, a.get()).
template <class T>
bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator>(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns nullptr < a. The second function template returns a < nullptr.
template <class T>
bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator<=(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns !(nullptr < a). The second function template returns !(a < nullptr).
template <class T>
bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator>=(nullptr_t, const shared_ptr<T>& a) noexcept;
template<class T>
void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
template<class T, class U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
[ Note: The seemingly equivalent expression shared_ptr<T>(static_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice. — end note ]
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression dynamic_cast<T*>((U*)0) shall be well formed and shall have well defined behavior.
[ Note: The seemingly equivalent expression shared_ptr<T>(dynamic_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice. — end note ]
template<class T, class U>
shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
[ Note: The seemingly equivalent expression shared_ptr<T>(const_cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice. — end note ]
template<class T, class U>
shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class D, class T>
D* get_deleter(const shared_ptr<T>& p) noexcept;
Returns: If p owns a deleter d of type cv-unqualified D, returns addressof(d); otherwise returns nullptr. The returned pointer remains valid as long as there exists a shared_ptr instance that owns d. [ Note: It is unspecified whether the pointer remains valid longer than that. This can happen if the implementation doesn't destroy the deleter until all weak_ptr instances that share ownership with p have been destroyed. — end note ]
template<class E, class T, class Y>
basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p);