20 General utilities library [utilities]

20.11 Smart pointers [smartptr]

20.11.3 Class template shared_­ptr [util.smartptr.shared]

20.11.3.1 Constructors [util.smartptr.shared.const]

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;
Postconditions: use_­count() == 0 && get() == nullptr.
template<class Y> explicit shared_ptr(Y* p);
Mandates: Y is a complete type.
Constraints: When T is an array type, 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, the expression delete p is well-formed and Y* is convertible to T*.
Preconditions: The expression delete[] p, when T is an array type, or delete p, when T is not an array type, has well-defined behavior, and does 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.
Postconditions: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
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);
Constraints: is_­move_­constructible_­v<D> is true, and d(p) is a well-formed expression.
For the first two overloads:
  • If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
  • If T is not an array type, then Y* is convertible to T*.
Preconditions: Construction of d and a deleter of type D initialized with std​::​move(d) do not throw exceptions.
The expression d(p) has well-defined behavior and does not throw exceptions.
A meets the Cpp17Allocator requirements (Table 36).
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.
Postconditions: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
Effects: Constructs a shared_­ptr instance that stores p and shares ownership with the initial value of r.
Postconditions: get() == p.
For the second overload, r is empty and r.get() == nullptr.
[Note
:
To avoid the possibility of a dangling pointer, the user of this constructor should 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;
Constraints: For the second constructor, 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.
Postconditions: get() == r.get() && use_­count() == r.use_­count().
shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: Move constructs a shared_­ptr instance from r.
Postconditions: *this shall contain the old value of r.
r shall be empty.
r.get() == nullptr.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
Constraints: Y* is compatible with T*.
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.
Postconditions: use_­count() == r.use_­count().
Throws: bad_­weak_­ptr when r.expired().
template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Constraints: Y* is compatible with T* and unique_­ptr<Y, D>​::​pointer is convertible to element_­type*.
Effects: If r.get() == nullptr, equivalent to shared_­ptr().
Otherwise, if D is not a reference type, equivalent to shared_­ptr(r.release(), r.get_­deleter()).
Otherwise, equivalent to shared_­ptr(r.release(), ref(r.get_­deleter())).
If an exception is thrown, the constructor has no effect.