std:: make_shared, std:: make_shared_for_overwrite
Defined in header
<memory>
|
||
template
<
class
T,
class
...
Args
>
shared_ptr < T > make_shared ( Args && ... args ) ; |
(1) |
(since C++11)
(T is not array) |
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N ) ; |
(2) |
(since C++20)
(T is U[]) |
template
<
class
T
>
shared_ptr < T > make_shared ( ) ; |
(3) |
(since C++20)
(T is U[N]) |
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N, const std:: remove_extent_t < T > & u ) ; |
(4) |
(since C++20)
(T is U[]) |
template
<
class
T
>
shared_ptr < T > make_shared ( const std:: remove_extent_t < T > & u ) ; |
(5) |
(since C++20)
(T is U[N]) |
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( ) ; |
(6) |
(since C++20)
(T is not U[]) |
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( std:: size_t N ) ; |
(7) |
(since C++20)
(T is U[]) |
T
and wraps it in a
std::shared_ptr
using
args
as the parameter list for the constructor of
T
. The object is constructed as if by the expression
::
new
(
pv
)
T
(
std::
forward
<
Args
>
(
args
)
...
)
, where
pv
is an internal
void
*
pointer to storage suitable to hold an object of type
T
. The storage is typically larger than
sizeof
(
T
)
in order to use one allocation for both the control block of the shared pointer and the
T
object. The
std::shared_ptr
constructor called by this function enables
shared_from_this
with a pointer to the newly constructed object of type
T
.
This overload participates in overload resolution only if T is not an array type. |
(since C++20) |
U
is not an array type, then this is performed as if by the same placement-new expression as in
(1)
; otherwise, this is performed as if by initializing every non-array element of the (possibly multidimensional) array with the corresponding element from
u
with the same placement-new expression as in
(1)
. The overload
(4)
creates an array of size
N
along the first dimension. The array elements are initialized in ascending order of their addresses, and when their lifetime ends are destroyed in the reverse order of their original construction.
T
is not an array type and
(3)
if
T
is
U
[
N
]
, except that the created object is
default-initialized
.
In each case, the object
(or individual elements if
T
is an array type)
(since C++20)
will be destroyed by
p
-
>
~X
(
)
, where
p
is a pointer to the object and
X
is its type.
Parameters
args | - |
list of arguments with which an instance of
T
will be constructed
|
N | - | array size to use |
u | - | the initial value to initialize every element of the array |
Return value
std::shared_ptr
of an instance of type
T
.
Exceptions
May throw
std::bad_alloc
or any exception thrown by the constructor of
T
. If an exception is thrown, the functions have no effect.
If an exception is thrown during the construction of the array, already-initialized elements are destroyed in reverse order.
(since C++20)
Notes
This function may be used as an alternative to std:: shared_ptr < T > ( new T ( args... ) ) . The trade-offs are:
-
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
performs at least two allocations (one for the object
T
and one for the control block of the shared pointer), while std :: make_shared < T > typically performs only one allocation (the standard recommends, but does not require this; all known implementations do this). -
If any
std::weak_ptr
references the control block created by
std::make_shared
after the lifetime of all shared owners ended, the memory occupied byT
persists until all weak owners get destroyed as well, which may be undesirable if sizeof ( T ) is large. -
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
may call a non-public constructor of
T
if executed in context where it is accessible, whilestd::make_shared
requires public access to the selected constructor. -
Unlike the
std::shared_ptr
constructors,
std::make_shared
does not allow a custom deleter. -
std::make_shared
uses :: new , so if any special behavior has been set up using a class-specific operator new , it will differ from std:: shared_ptr < T > ( new T ( args... ) ) .
|
(until C++20) |
|
(until C++17) |
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
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
)
)
;
.
The assignment to the
weak_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
-
>
weak_this
.
expired
(
)
in the code above makes sure that
weak_this
is not reassigned if it already indicates an owner. This test is required as of C++17.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_shared_ptr_arrays
|
201707L | (C++20) |
Array support of
std::make_shared
; overloads
(
2-5
)
|
__cpp_lib_smart_ptr_for_overwrite
|
202002L | (C++20) |
Smart pointer creation with default initialization (
std::allocate_shared_for_overwrite
,
std::make_shared_for_overwrite
,
std::make_unique_for_overwrite
); overloads
(
6,7
)
|
Example
#include <iostream> #include <memory> #include <type_traits> #include <vector> struct C { // constructors needed (until C++20) C(int i) : i(i) {} C(int i, float f) : i(i), f(f) {} int i; float f{}; }; int main() { // using `auto` for the type of `sp1` auto sp1 = std::make_shared<C>(1); // overload (1) static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>); std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n"; // being explicit with the type of `sp2` std::shared_ptr<C> sp2 = std::make_shared<C>(2, 3.0f); // overload (1) static_assert(std::is_same_v<decltype(sp2), std::shared_ptr<C>>); static_assert(std::is_same_v<decltype(sp1), decltype(sp2)>); std::cout << "sp2->{ i:" << sp2->i << ", f:" << sp2->f << " }\n"; // shared_ptr to a value-initialized float[64]; overload (2): std::shared_ptr<float[]> sp3 = std::make_shared<float[]>(64); // shared_ptr to a value-initialized long[5][3][4]; overload (2): std::shared_ptr<long[][3][4]> sp4 = std::make_shared<long[][3][4]>(5); // shared_ptr to a value-initialized short[128]; overload (3): std::shared_ptr<short[128]> sp5 = std::make_shared<short[128]>(); // shared_ptr to a value-initialized int[7][6][5]; overload (3): std::shared_ptr<int[7][6][5]> sp6 = std::make_shared<int[7][6][5]>(); // shared_ptr to a double[256], where each element is 2.0; overload (4): std::shared_ptr<double[]> sp7 = std::make_shared<double[]>(256, 2.0); // shared_ptr to a double[7][2], where each double[2] // element is {3.0, 4.0}; overload (4): std::shared_ptr<double[][2]> sp8 = std::make_shared<double[][2]>(7, {3.0, 4.0}); // shared_ptr to a vector<int>[4], where each vector // has contents {5, 6}; overload (4): std::shared_ptr<std::vector<int>[]> sp9 = std::make_shared<std::vector<int>[]>(4, {5, 6}); // shared_ptr to a float[512], where each element is 1.0; overload (5): std::shared_ptr<float[512]> spA = std::make_shared<float[512]>(1.0); // shared_ptr to a double[6][2], where each double[2] element // is {1.0, 2.0}; overload (5): std::shared_ptr<double[6][2]> spB = std::make_shared<double[6][2]>({1.0, 2.0}); // shared_ptr to a vector<int>[4], where each vector // has contents {5, 6}; overload (5): std::shared_ptr<std::vector<int>[4]> spC = std::make_shared<std::vector<int>[4]>({5, 6}); }
Output:
sp1->{ i:1, f:0 } sp2->{ i:2, f:3 }
See also
constructs new
shared_ptr
(public member function) |
|
creates a shared pointer that manages a new object allocated using an allocator
(function template) |
|
(C++11)
|
allows an object to create a
shared_ptr
referring to itself
(class template) |
(C++14)
(C++20)
|
creates a unique pointer that manages a new object
(function template) |
allocation functions
(function) |