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>;
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() { }
~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, 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;
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>;
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 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;
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)) {
}
—
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 (
[util.smartptr.enab]),
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;
Effects: Constructs an empty
shared_ptr object
. Postconditions: use_count() == 0 && get() == nullptr. 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
.Postconditions: use_count() == 1 && get() == p. Throws: bad_alloc, or an
implementation-defined exception when a resource other than memory could not be obtained
. 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
. 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
. 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;
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;
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. 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;
Remarks: The second constructor shall not participate in overload resolution unless
Y* is compatible with
T*. Effects: Move constructs a
shared_ptr instance from
r. Postconditions: *this shall contain the old value of
r. 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
.Postconditions: use_count() == r.use_count(). Throws: bad_weak_ptr when
r.expired(). 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*. 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
.~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;
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). element_type* get() const noexcept;
Returns: The stored pointer
. 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;
Requires: get() != 0 && i >= 0. 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: get() == nullptr
does not imply a specific return value of
use_count(). —
end note ]
[
Note: weak_ptr<T>::lock()
can affect the return value of
use_count(). —
end note ]
[
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);
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
. 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: 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 ]
[
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<>()(a.get(), b.get()). [
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;
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*>((U*)0) shall
be well formed
. Returns:
shared_ptr<T>(r, static_cast<typename shared_ptr<T>::element_type*>(r.get()))
[
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
. Returns:
When
dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())
returns a nonzero value
p,
shared_ptr<T>(r, p).Otherwise,
shared_ptr<T>().
[
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*>((U*)0) shall
be well formed
. Returns:
shared_ptr<T>(r, const_cast<typename shared_ptr<T>::element_type*>(r.get()))
[
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;
Requires: The expression
reinterpret_cast<T*>((U*)0)
shall be well formed
. Returns:
shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))
[
Note: The seemingly equivalent expression
shared_ptr<T>(reinterpret_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
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);
Effects: As if by: os << p.get();
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:
using element_type = T;
constexpr weak_ptr() noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
~weak_ptr();
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;
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(const shared_ptr<U>& b) const;
template<class U> bool owner_before(const weak_ptr<U>& b) const;
};
template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>;
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;
Remarks: The second and third constructors shall not participate in
overload resolution unless
Y* is compatible with
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;
Remarks: The second constructor shall not participate in overload resolution unless
Y* is compatible with
T*. Effects: Move constructs a
weak_ptr instance from
r. Postconditions: *this shall contain the old value of
r. ~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. bool expired() const noexcept;
Returns: use_count() == 0. shared_ptr<T> lock() const noexcept;
Returns: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically
. template<class U> bool owner_before(const shared_ptr<U>& b) const;
template<class U> bool owner_before(const weak_ptr<U>& 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). 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: As if by
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. Effects: As if by
p->swap(r). 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
. Effects: As if by
p->swap(r). 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
. The
failure argument shall not be
memory_order_release nor
memory_order_acq_rel.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
. The weak form may fail spuriously
.