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 object is empty if it does not own a pointer.
namespace std {
template<class T> class shared_ptr {
public:
typedef T element_type;
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, T* 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> shared_ptr(auto_ptr<Y>&& r);
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
constexpr shared_ptr(nullptr_t) : shared_ptr() { }
~shared_ptr();
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> shared_ptr& operator=(auto_ptr<Y>&& r);
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);
T* get() const noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
long use_count() const noexcept;
bool unique() const noexcept;
explicit operator bool() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
};
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);
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;
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;
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 D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
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 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)) {
}
— 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.
constexpr shared_ptr() noexcept;
Effects: Constructs an empty shared_ptr object.
Postconditions: use_count() == 0 && get() == nullptr.
template<class Y> explicit shared_ptr(Y* p);
Requires: p shall be convertible to T*.
Y shall be a complete type. The expression delete p
shall be well formed, shall have well defined behavior, and shall not
throw exceptions.
Effects: Constructs a shared_ptr object that owns the pointer
p.
Postconditions: use_count() == 1 && get() == p.
Throws: bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
Exception safety: If an exception is thrown, delete p is
called.
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: p shall be convertible to T*. D shall be
CopyConstructible. The copy constructor and destructor of D
shall not throw exceptions. The expression d(p) shall be
well formed, shall have well defined behavior, and shall not throw exceptions.
A shall be an allocator ([allocator.requirements]).
The copy constructor and destructor of A shall not throw exceptions.
Effects: Constructs a shared_ptr object that owns the
object p and the deleter d.
The second and fourth constructors shall use a copy of a to
allocate memory for internal use.
Postconditions: use_count() == 1 && get() == p.
Throws: bad_alloc, or an implementation-defined exception
when a resource other than memory could not be obtained.
Exception safety: If an exception is thrown, d(p) is called.
template<class Y> shared_ptr(const shared_ptr<Y>& r, T* p) noexcept;
Effects: Constructs a shared_ptr instance that
stores p and shares ownership with r.
Postconditions: get() == p && use_count() == r.use_count()
[ 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;
Remark:
The second constructor shall not participate in overload resolution unless
Y* is implicitly convertible to 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;
Remark: The second constructor shall not participate in overload resolution unless
Y* is convertible to 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);
Requires: Y* shall be convertible to T*.
Effects: Constructs a shared_ptr object that shares ownership with
r and stores a copy of the pointer stored in r.
Postconditions: use_count() == r.use_count().
Throws: bad_weak_ptr when r.expired().
Exception safety: If an exception is thrown, the constructor has no
effect.
template<class Y> shared_ptr(auto_ptr<Y>&& r);
Requires: r.release() shall be convertible to T*.
Y shall be a complete type. The expression delete
r.release() shall be well formed, shall have well defined behavior,
and shall not throw exceptions.
Effects: Constructs a shared_ptr object that stores and owns
r.release().
Postconditions: use_count() == 1 && r.get() == nullptr.
Throws: bad_alloc, or an implementation-defined exception when a
resource other than memory could not be obtained.
Exception safety: If an exception is thrown, the constructor has no
effect.
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Effects: Equivalent to shared_ptr(r.release(), r.get_deleter()) when
D is not a reference type, otherwise shared_ptr(r.release(),
ref(r.get_deleter())).
Exception safety: If an exception is thrown, the constructor has no effect.
~shared_ptr();
Effects:
If *this is empty or shares ownership with another
shared_ptr instance (use_count() > 1), there are no side effects.
Otherwise, if *this owns an object
p and a deleter d, d(p) is called.
Otherwise, *this owns a pointer p,
and delete p is called.
[ Note: Since the destruction of *this
decreases the number of instances that share ownership with *this
by one,
after *this has been destroyed
all shared_ptr instances that shared ownership with
*this will report a use_count() that is one less
than its previous value. — end note ]
shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
Effects: Equivalent to shared_ptr(r).swap(*this).
[ 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;
Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).
template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).
void swap(shared_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to shared_ptr().swap(*this).
template<class Y> void reset(Y* p);
Effects: Equivalent to shared_ptr(p).swap(*this).
template<class Y, class D> void reset(Y* p, D d);
Effects: Equivalent to shared_ptr(p, d).swap(*this).
template<class Y, class D, class A> void reset(Y* p, D d, A a);
Effects: Equivalent to shared_ptr(p, d, a).swap(*this).
T* get() const noexcept;
Returns: the stored pointer.
T& operator*() const noexcept;
Remarks: When T is 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;
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: use_count() is not necessarily
efficient. — end note ]
bool unique() const noexcept;
Returns: use_count() == 1.
[ Note: unique() may be faster than use_count(). If you are
using unique() to implement copy on write, do not rely on a
specific value when get() == nullptr. — end note ]
explicit operator bool() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
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);
Requires: The expression ::new (pv) T(std::forward<Args>(args)...),
where pv has type void* and points to storage suitable
to hold an object of type T, shall be well formed. A shall
be an allocator ([allocator.requirements]). The copy constructor
and destructor of A shall not throw exceptions.
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.
Postconditions: get() != 0 && use_count() == 1
Throws: bad_alloc, or an exception thrown from
A::allocate or from the constructor of T.
Remarks: Implementations should
perform no more than one memory allocation. [ Note: This provides
efficiency equivalent to an intrusive smart pointer. — end note ]
[ Note: These functions will typically allocate more memory
than sizeof(T) to allow for internal bookkeeping structures such
as the reference counts. — end note ]
template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: a.get() == b.get().
template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: less<V>()(a.get(), b.get()),
where V is the composite pointer type (Clause [expr]) of T* and U*.
[ Note:
Defining a comparison operator 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<T*>()(a.get(), nullptr).
The second function template returns
less<T*>()(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;
Returns:
The first function template returns !(a < nullptr).
The second function template returns !(nullptr < a).
template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).
template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression static_cast<T*>(r.get()) shall
be well formed.
Returns: If r is empty, an empty
shared_ptr<T>; otherwise, a shared_ptr<T> object that
stores static_cast<T*>(r.get()) and shares ownership
with r.
Postconditions: w.get() == static_cast<T*>(r.get()) and
w.use_count() == r.use_count(), where w is the return value.
[ 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*>(r.get())
shall be well formed and shall have well defined behavior.
Returns:
When dynamic_cast<T*>(r.get()) returns a nonzero value, a
shared_ptr<T> object that stores a copy of it and shares
ownership with r;
Otherwise, an empty shared_ptr<T> object.
Postcondition: w.get() == dynamic_cast<T*>(r.get()), where w is the return value.
[ 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;
Requires: The expression const_cast<T*>(r.get()) shall
be well formed.
Returns: If r is empty, an empty shared_ptr<T>; otherwise, a
shared_ptr<T> object that stores const_cast<T*>(r.get()) and shares
ownership with r.
Postconditions: w.get() == const_cast<T*>(r.get()) and
w.use_count() == r.use_count(), where w is the return value.
[ 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 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 &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, shared_ptr<Y> const& p);
The weak_ptr class template stores a weak reference to an object
that is already managed by a shared_ptr. To access the object, a
weak_ptr can be converted to a shared_ptr using the member
function lock.
namespace std {
template<class T> class weak_ptr {
public:
typedef T element_type;
constexpr weak_ptr() noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr const& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
~weak_ptr();
weak_ptr& operator=(weak_ptr const& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept;
template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept;
weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
long use_count() const noexcept;
bool expired() const noexcept;
shared_ptr<T> lock() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
};
template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
}
Specializations of weak_ptr shall be CopyConstructible and
CopyAssignable, allowing their use in standard
containers. The template parameter T of weak_ptr may be an
incomplete type.
constexpr weak_ptr() noexcept;
Effects: Constructs an empty weak_ptr object.
Postconditions: use_count() == 0.
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Remark: The second and third constructors shall not participate in
overload resolution unless Y* is implicitly convertible to T*.
Effects: If r is empty, constructs
an empty weak_ptr object; otherwise, constructs
a weak_ptr object that shares ownership
with r and stores a copy of the pointer stored in r.
Postconditions: use_count() == r.use_count().
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Remark: The second constructor shall not participate in overload resolution unless
Y* is implicitly convertible to T*.
Effects: Move-constructs a weak_ptr instance from r.
Postconditions: *this shall contain the old value of r.
r shall be empty. r.use_count() == 0.
~weak_ptr();
Effects: Destroys this weak_ptr object but has no
effect on the object its stored pointer points to.
weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to weak_ptr(r).swap(*this).
Remarks: The implementation may meet the effects (and the
implied guarantees) via different means, without creating a temporary.
weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
Effects: Equivalent to weak_ptr(std::move(r)).swap(*this).
void swap(weak_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to weak_ptr().swap(*this).
long use_count() const noexcept;
Returns: 0 if *this is empty;
otherwise, the number of shared_ptr instances
that share ownership with *this.
[ Note: use_count() is not necessarily
efficient. — end note ]
bool expired() const noexcept;
Returns: use_count() == 0.
[ Note: expired() may be faster
than use_count(). — end note ]
shared_ptr<T> lock() const noexcept;
Returns: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically.
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
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> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).
A class T can inherit from enable_shared_from_this<T>
to inherit the shared_from_this member functions that obtain
a shared_ptr instance pointing to *this.
[ Example:
struct X: public enable_shared_from_this<X> {
};
int main() {
shared_ptr<X> p(new X);
shared_ptr<X> q = p->shared_from_this();
assert(p == q);
assert(!(p < q ) && !(q < p)); }
— end example ]
namespace std {
template<class T> class enable_shared_from_this {
protected:
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(enable_shared_from_this const&) noexcept;
enable_shared_from_this& operator=(enable_shared_from_this const&) noexcept;
~enable_shared_from_this();
public:
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
};
}
The template parameter T of enable_shared_from_this
may be an incomplete type.
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
Effects: Constructs an enable_shared_from_this<T> object.
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
~enable_shared_from_this();
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
Requires: enable_shared_from_this<T> shall be an accessible base
class of T. *this shall be a subobject of an object t of
type T. There shall be at least one shared_ptr instance p
that owns &t.
Returns: A shared_ptr<T> object r
that shares ownership with p.
Postconditions: r.get() == this.
[ Note: A possible implementation is shown below:
template<class T> class enable_shared_from_this {
private:
weak_ptr<T> __weak_this;
protected:
constexpr enable_shared_from_this() : __weak_this() { }
enable_shared_from_this(enable_shared_from_this const &) { }
enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; }
~enable_shared_from_this() { }
public:
shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); }
shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); }
};
The shared_ptr constructors that create unique pointers
can detect the presence of an enable_shared_from_this base and
assign the newly created shared_ptr to its __weak_this
member. — end note ]
Concurrent access to a shared_ptr object from multiple threads does not
introduce a data race if the access is done exclusively via the functions in
this section and the instance is passed as their first argument.
The meaning of the arguments of type memory_order is explained in [atomics.order].
template<class T>
bool atomic_is_lock_free(const shared_ptr<T>* p);
Requires: p shall not be null.
Returns: true if atomic access to *p is lock-free, false otherwise.
template<class T>
shared_ptr<T> atomic_load(const shared_ptr<T>* p);
Requires: p shall not be null.
Returns: atomic_load_explicit(p, memory_order_seq_cst).
template<class T>
shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
Requires: p shall not be null.
Requires: mo shall not be memory_order_release or memory_order_acq_rel.
template<class T>
void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
Requires: p shall not be null.
Effects: atomic_store_explicit(p, r, memory_order_seq_cst).
template<class T>
void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
Requires: p shall not be null.
Requires: mo shall not be memory_order_acquire or memory_order_acq_rel.
template<class T>
shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
Requires: p shall not be null.
Returns: atomic_exchange_explicit(p, r, memory_order_seq_cst).
template<class T>
shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r,
memory_order mo);
Requires: p shall not be null.
Returns: The previous value of *p.
template<class T>
bool atomic_compare_exchange_weak(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
Requires: p shall not be null and v shall not be null.
Returns: atomic_compare_exchange_weak_explicit(p, v, w,
memory_order_seq_cst, memory_order_seq_cst).
template<class T>
bool atomic_compare_exchange_strong(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
Returns: atomic_compare_exchange_strong_explicit(p, v, w,
memory_order_seq_cst, memory_order_seq_cst).
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);
Requires: p shall not be null and v shall not be null.
Requires: failure shall not be memory_order_release,
memory_order_acq_rel, or stronger than success.
Effects: If *p is equivalent to *v, assigns w to
*p and has synchronization semantics corresponding to the value of
success, otherwise assigns *p to *v and has
synchronization semantics corresponding to the value of failure.
Returns: true if *p was equivalent to *v, false otherwise.
Remarks: two shared_ptr objects are equivalent if they store the same
pointer value and share ownership.