std::shared_ptr<T>::shared_ptr
Declarations
// 1)
constexpr shared_ptr() noexcept;
// 2)
constexpr shared_ptr( std::nullptr_t ) noexcept;
// 3)
template< class Y >
explicit shared_ptr( Y* ptr );
// 4)
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
// 5)
template< class Deleter >
shared_ptr( std::nullptr_t ptr, Deleter d );
// 6)
template< class Y, class Deleter, class Alloc >
shared_ptr( Y* ptr, Deleter d, Alloc alloc );
// 7)
template< class Deleter, class Alloc >
shared_ptr( std::nullptr_t ptr, Deleter d, Alloc alloc );
// 8)
template< class Y >
shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept;
// 9)
template< class Y >
shared_ptr( shared_ptr<Y>&& r, element_type* ptr ) noexcept; // Since C++20
// 10)
shared_ptr( const shared_ptr& r ) noexcept;
// 11)
template< class Y >
shared_ptr( const shared_ptr<Y>& r ) noexcept;
// 12)
shared_ptr( shared_ptr&& r ) noexcept;
// 13)
template< class Y >
shared_ptr( shared_ptr<Y>&& r ) noexcept;
// 14)
template< class Y >
explicit shared_ptr( const std::weak_ptr<Y>& r );
// 15)
template< class Y >
shared_ptr( std::auto_ptr<Y>&& r ); // Removed in C++17
// 16)
template< class Y, class Deleter >
shared_ptr( std::unique_ptr<Y, Deleter>&& r );
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).
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 toT*
(Until C++17). -
If T is an array type
U[N]
, (3-4,6) do not participate in overload resolution ifY(*)[N]
is not convertible toT*
. IfT
is an array typeU[]
, (3-4,6) do not participate in overload resolution ifY(*)[]
is not convertible toT*
. Otherwise, (3-4,6) do not participate in overload resolution ifY*
is not convertible toT*
(Since C++17).
Additionally:
-
3) Uses the delete-expression delete
ptr
ifT
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 expressiond(ptr)
must be well formed, have well-defined behavior and not throw any exceptions. The construction ofd
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 ifstd::is_move_constructible<D>::value
isfalse
(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 anAllocator
.
-
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 this shared_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, calling get()
on this shared_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) of r.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 if Y*
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 if Y*
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 to T*
(until C++17).
This overload participates in overload resolution only if Y*
is compatible with T*
(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 empty std::shared_ptr
in that case.
Constructs a shared_ptr
that stores and owns the object formerly owned by r
. Y*
must be convertible to T*
. 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 withT*
. Ifr.get()
is anull
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), and (6) enable shared_from_this
with ptr
, and the overload (13) enables
shared_from_this
with the pointer returned by r.release()
.
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
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.
11)
std::bad_weak_ptr
if r.expired() == true
. The constructor has no effect in this case.
12)
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.
13)
If an exception is thrown, the constructor has no effects.
Notes
A constructor enables shared_from_this
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 the statement:
if (ptr != nullptr && ptr->weak_this.expired())
ptr->weak_this = std::shared_ptr<std::remove_cv_t<U>>(
*this, const_cast<std::remove_cv_t<U>*>(ptr));
Where weak_this
is the hidden mutable std::weak_ptr
member of std::enable_shared_from_this
.
The assignment to the weak_this
member 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->weak_this.expired()
in the exposition code above makes sure that weak_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[]>
:
std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int> ptr(std::move(arr));
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.
Example
#include <memory>
#include <iostream>
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<Foo> sh1;
}
{
std::cout
<< "2) constructor with object\n";
std::shared_ptr<Foo> sh2(new Foo{10});
std::cout
<< "sh2.use_count(): "
<< sh2.use_count() << '\n';
std::shared_ptr<Foo> 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<Foo> sh4(new Foo{11}, D());
std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p) {
std::cout
<< "Call delete from lambda... p->id="
<< p->id << "\n";
delete p;
});
}
}
1) constructor with no managed object
2) constructor with object
Foo::Foo(10)
sh2.use_count(): 1
sh2.use_count(): 2
sh3.use_count(): 2
Foo::~Foo(), id=10
3) 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
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 |