std::shared_ptr::shared_ptr - cppreference.com (original) (raw)
constexpr shared_ptr() noexcept; | (1) | |
---|---|---|
constexpr shared_ptr( std::nullptr_t ) noexcept; | (2) | |
template< class Y > explicit shared_ptr( Y* ptr ); | (3) | |
template< class Y, class Deleter > shared_ptr( Y* ptr, Deleter d ); | (4) | |
template< class Deleter > shared_ptr( std::nullptr_t ptr, Deleter d ); | (5) | |
template< class Y, class Deleter, class Alloc > shared_ptr( Y* ptr, Deleter d, Alloc alloc ); | (6) | |
template< class Deleter, class Alloc > shared_ptr( std::nullptr_t ptr, Deleter d, Alloc alloc ); | (7) | |
template< class Y > shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept; | (8) | |
template< class Y > shared_ptr( shared_ptr<Y>&& r, element_type* ptr ) noexcept; | (8) | (since C++20) |
shared_ptr( const shared_ptr& r ) noexcept; | (9) | |
template< class Y > shared_ptr( const shared_ptr<Y>& r ) noexcept; | (9) | |
shared_ptr( shared_ptr&& r ) noexcept; | (10) | |
template< class Y > shared_ptr( shared_ptr<Y>&& r ) noexcept; | (10) | |
template< class Y > explicit shared_ptr( const std::weak_ptr<Y>& r ); | (11) | |
template< class Y > shared_ptr( std::auto_ptr<Y>&& r ); | (12) | (removed in C++17) |
template< class Y, class Deleter > shared_ptr( std::unique_ptr<Y, Deleter>&& r ); | (13) |
Constructs new shared_ptr
from a variety of pointer types that refer to an object to manage.
For the purposes of the description below, a pointer type Y* is said to be compatible with a pointer type T* if either Y* is convertible to T* or Y is the array type U[N] and T is U cv [] (where cv is some set of cv-qualifiers). | (since C++17) |
---|
1,2) Constructs a shared_ptr
with no managed object, i.e. empty shared_ptr
.
3-7) Constructs a shared_ptr
with ptr as the pointer to the managed object.
For (3,4,6), Y* must be convertible to T*. | (until C++17) |
---|---|
If T is an array type U[N], (3,4,6) do not participate in overload resolution if Y(*)[N] is an invalid type or not convertible to T*. If T is an array type U[], (3,4,6) do not participate in overload resolution if Y(*)[] is an invalid type or not convertible to T*. Otherwise, (3,4,6) do not participate in overload resolution if Y* is not convertible to T*. | (since C++17) |
Additionally:
- Uses the delete-expression delete ptr if
T
is not an array type; delete[] ptr ifT
is an array type(since C++17) as the deleter.Y
must be a complete type. The delete expression must be well-formed, have well-defined behavior and not throw any exceptions. This constructor additionally does not participate in overload resolution if the delete expression is not well-formed.(since C++17)
4,5) Uses the specified deleter d as the deleter. The expression d(ptr) must be well formed, have well-defined behavior and not throw any exceptions. The construction of d and of the stored deleter copied from it must not throw exceptions.
Deleter must be CopyConstructible. | (until C++17) |
---|---|
These constructors additionally do not participate in overload resolution if the expression d(ptr) is not well-formed, or if std::is_move_constructible_v<D> is false. | (since C++17) |
6,7) Same as (4,5), but additionally uses a copy of alloc for allocation of data for internal use. Alloc
must be an Allocator.
The aliasing constructor: constructs a
shared_ptr
which shares ownership information with the initial value of r, but holds an unrelated and unmanaged pointer ptr. If thisshared_ptr
is the last of the group to go out of scope, it will call the stored deleter for the object originally managed by r. However, callingget()
on thisshared_ptr
will always return a copy of ptr. It is the responsibility of the programmer to make sure that this ptr remains valid as long as this shared_ptr exists, such as in the typical use cases where ptr is a member of the object managed by r or is an alias (e.g., downcast) ofr.get()
For the second overload taking an rvalue, r is empty and r.get() == nullptr after the call.(since C++20)Constructs a
shared_ptr
which shares ownership of the object managed by r. If r manages no object, *this manages no object either. The template overload doesn't participate in overload resolution ifY*
is not implicitly convertible to(until C++17)compatible with(since C++17)T*
.Move-constructs a
shared_ptr
from r. After the construction, *this contains a copy of the previous state of r, r is empty and its stored pointer is null. The template overload doesn't participate in overload resolution ifY*
is not implicitly convertible to(until C++17)compatible with(since C++17)T*
.Constructs a
shared_ptr
which shares ownership of the object managed by r.Y*
must be implicitly convertible toT*
.(until C++17)This overload participates in overload resolution only ifY*
is compatible withT*
.(since C++17) Note that r.lock() may be used for the same purpose: the difference is that this constructor throws an exception if the argument is empty, while std::weak_ptr<T>::lock() constructs an emptystd::shared_ptr
in that case.Constructs a
shared_ptr
that stores and owns the object formerly owned by r.Y*
must be convertible toT*
. After construction, r is empty.Constructs a
shared_ptr
which manages the object currently managed by r. The deleter associated with r is stored for future deletion of the managed object. r manages no object after the call.
This overload doesn't participate in overload resolution if std::unique_ptr<Y, Deleter>::pointer is not compatible with T*. If r.get() is a null pointer, this overload is equivalent to the default constructor (1). | (since C++17) |
---|
If Deleter
is a reference type, it is equivalent to shared_ptr(r.release(), std::ref(r.get_deleter()). Otherwise, it is equivalent to shared_ptr(r.release(), std::move(r.get_deleter())).
When T
is not an array type, the overloads (3,4,6) enable shared_from_this
with ptr, and the overload (13) enables shared_from_this
with the pointer returned by r.release().
Contents
[edit] Parameters
ptr | - | a pointer to an object to manage |
---|---|---|
d | - | a deleter to use to destroy the object |
alloc | - | an allocator to use for allocations of data for internal use |
r | - | another smart pointer to share the ownership to or acquire the ownership from |
[edit] Postconditions
get() equals ptr. For the second overload, r is empty and r.get() equals nullptr.
r shall be empty and r.get() shall equal nullptr, and *this shall be the old value of r.
use_count() equals 1 and r.get() equals nullptr.
[edit] Exceptions
- std::bad_alloc if required additional memory could not be obtained. May throw implementation-defined exception for other errors. If an exception occurs, this calls delete ptr if
T
is not an array type, and calls delete[] ptr otherwise(since C++17).
4-7) std::bad_alloc if required additional memory could not be obtained. May throw implementation-defined exception for other errors. d(ptr) is called if an exception occurs.
std::bad_weak_ptr if r.expired() == true. The constructor has no effect in this case.
std::bad_alloc if required additional memory could not be obtained. May throw implementation-defined exception for other errors. This constructor has no effect if an exception occurs.
If an exception is thrown, the constructor has no effects.
[edit] Notes
A constructor enables sharedfromthis
with a pointer ptr of type U*
means that it determines if U
has an unambiguous and accessible(since C++17) base class that is a specialization of std::enable_shared_from_this, and if so, the constructor evaluates if (ptr != nullptr && ptr->_[weakthis](../enable%5Fshared%5Ffrom%5Fthis.html#weak%5Fthis "cpp/memory/enable shared from this")_
.expired())ptr\-\>`_[weakthis](../enable%5Fshared%5Ffrom%5Fthis.html#weak%5Fthis "cpp/memory/enable shared from this")_` ` `\= [std::shared\_ptr](../shared%5Fptr.html)<[std::remove\_cv\_t](../../types/remove%5Fcv.html)<U\>>
(*this, const_cast<std::remove_cv_t<U>*>(ptr)); .
The assignment to the _[weakthis](../enable%5Fshared%5Ffrom%5Fthis.html#weak%5Fthis "cpp/memory/enable shared from this")_
is not atomic and conflicts with any potentially concurrent access to the same object. This ensures that future calls to shared_from_this() would share ownership with the std::shared_ptr created by this raw pointer constructor.
The test ptr->_[weakthis](../enable%5Fshared%5Ffrom%5Fthis.html#weak%5Fthis "cpp/memory/enable shared from this")_
.expired() in the code above makes sure that _[weakthis](../enable%5Fshared%5Ffrom%5Fthis.html#weak%5Fthis "cpp/memory/enable shared from this")_
is not reassigned if it already indicates an owner. This test is required as of C++17.
The raw pointer overloads assume ownership of the pointed-to object. Therefore, constructing a shared_ptr
using the raw pointer overload for an object that is already managed by a shared_ptr
, such as by shared_ptr(ptr.get()) is likely to lead to undefined behavior, even if the object is of a type derived from std::enable_shared_from_this.
Because the default constructor is constexpr
, static shared_ptrs are initialized as part of static non-local initialization, before any dynamic non-local initialization begins. This makes it safe to use a shared_ptr in a constructor of any static object.
In C++11 and C++14 it is valid to construct a std::shared_ptr<T> from a std::unique_ptr<T[]>:
Since the shared_ptr
obtains its deleter (a std::default_delete<T[]> object) from the std::unique_ptr, the array will be correctly deallocated.
This is no longer allowed in C++17. Instead the array form std::shared_ptr<T[]> should be used.
[edit] Example
#include
#include
struct Foo
{
int id{0};
Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i << ")\n"; }
Foo() { std::cout << "Foo::Foo(), id=" << id << '\n'; }
};
struct D
{
void operator()(Foo* p) const
{
std::cout << "Call delete from function object. Foo::id=" << p->id << '\n';
delete p;
}
};
int main()
{
{
std::cout << "1) constructor with no managed object\n";
std::shared_ptr sh1;
}
{
std::cout << "2) constructor with object\n";
std::shared_ptr sh2(new Foo{10});
std::cout << "sh2.use_count(): " << sh2.use_count() << '\n';
std::shared_ptr sh3(sh2);
std::cout << "sh2.use_count(): " << sh2.use_count() << '\n';
std::cout << "sh3.use_count(): " << sh3.use_count() << '\n';
}
{
std::cout << "3) constructor with object and deleter\n";
std::shared_ptr sh4(new Foo{11}, D());
std::shared_ptr sh5(new Foo{12}, [](auto p)
{
std::cout << "Call delete from lambda... p->id=" << p->id << '\n';
delete p;
});
}
}
Output:
- constructor with no managed object
- constructor with object Foo::Foo(10) sh2.use_count(): 1 sh2.use_count(): 2 sh3.use_count(): 2 Foo::~Foo(), id=10
- constructor with object and deleter
Foo::Foo(11)
Foo::Foo(12)
Call delete from lambda... p->id=12
Foo::
Foo(), id=12 Call delete from function object. Foo::id=11 Foo::Foo(), id=11
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 3548 | C++11 | the constructor from unique_ptr copy-constructed the deleter | move-constructs instead |