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) |
template< class T > shared_ptr<T> make_shared( std::size_t N ); |
(2) | (since C++20) |
template< class T > shared_ptr<T> make_shared(); |
(3) | (since C++20) |
template< class T > shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u ); |
(4) | (since C++20) |
template< class T > shared_ptr<T> make_shared( const std::remove_extent_t<T>& u ); |
(5) | (since C++20) |
template< class T > shared_ptr<T> make_shared_for_overwrite(); |
(6) | (since C++20) |
template< class T > shared_ptr<T> make_shared_for_overwrite( std::size_t N ); |
(7) | (since C++20) |
Allocates memory for an object and initialize the object with the supplied arguments. Returns a std::shared_ptr object managing the newly created object.
T
, and is constructed as if by ::new (pv) T(std::forward<Args>(args)...), where pv is a void* pointer to storage suitable to hold an object of type T
. If the object is to be destroyed, it is destroyed as if by pt->~T(), where pt is a pointer to that object of type T
.
This overload participates in overload resolution only if |
(since C++20) |
T
is an unbounded array type.T
. Each element has a default initial value.T
is a bounded array type.T
is an unbounded array type.T
. Each element has the initial value u.T
is a bounded array type.T
.
- If
T
is not an array type, the object is constructed as if by ::new (pv) T, where pv is a void* pointer to storage suitable to hold an object of typeT
. If the object is to be destroyed, it is destroyed as if by pt->~T(), where pt is a pointer to that object of typeT
. - If
T
is a bounded array type, the initial value is unspecified for each element.
T
is not an array type or is an bounded array type.T
is an unbounded array type.
Initializing and destroying array elementsArray elements of type
2,3) ::new (pv) U()
4,5) ::new (pv) U(u)
6,7) ::new (pv) U
When the lifetime of the object managed by the return std::shared_ptr ends, or when the initialization of an array element throws an exception, the initialized elements are destroyed in the reverse order of their original construction. For each array element of non-array type |
(since C++20) |
[edit] Parameters
args | - | list of arguments with which an object of T will be constructed
|
N | - | array size to use |
u | - | the initial value to initialize every element of the array |
[edit] Return value
std::shared_ptr to an object of type T
or std::remove_extent_t<T>[N] if T
is an unbounded array type(since C++20).
For the returned std::shared_ptr r, r.get() returns a non-null pointer and r.use_count() returns 1.
[edit] 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)
[edit] Notes
These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as reference counts.
These functions 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)
|
[edit] 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 }
[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 4024 | C++20 | it was unclear how the objects constructed instd::make_shared_for_overwrite are destroyed
|
made clear |
[edit] 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) |