On this page
std::make_shared, std::make_shared_for_overwrite
Defined in header <memory> |
||
---|---|---|
|
(1) | (since C++11) (T is not array) |
|
(2) | (since C++20) (T is U[]) |
|
(3) | (since C++20) (T is U[N]) |
|
(4) | (since C++20) (T is U[]) |
|
(5) | (since C++20) (T is U[N]) |
|
(6) | (since C++20) (T is not U[]) |
|
(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) |
std::remove_all_extents_t<T>
are value-initialized as if by placement-new expression ::new(pv) std::remove_all_extents_t<T>()
. The overload (2) 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.
u
. If 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 objectT
and one for the control block of the shared pointer), whilestd::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 bystd::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 ifsizeof(T)
is large. std::shared_ptr<T>(new T(args...))
may call a non-public constructor ofT
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-specificoperator new
, it will differ fromstd::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 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.
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) |
|
(C++20)
|
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) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared