Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/shared ptr/make shared"

From cppreference.com
< cpp‎ | memory‎ | shared ptr
m (Text replace - "_default_init" to "_for_overwrite")
m ({{c}}, .)
 
(15 intermediate revisions by 6 users not shown)
Line 3: Line 3:
 
{{dcl begin}}
 
{{dcl begin}}
 
{{dcl header|memory}}
 
{{dcl header|memory}}
{{dcl | num=1 | since=c++11|notes={{mark|T is not array}}|
+
{{dcl|num=1|since=c++11|notes={{mark|T is not array}}|
 
template< class T, class... Args >
 
template< class T, class... Args >
 
shared_ptr<T> make_shared( Args&&... args );
 
shared_ptr<T> make_shared( Args&&... args );
 
}}
 
}}
{{dcl | num=2 | since=c++20|notes={{mark|T is U[]}}|
+
{{dcla|num=2|since=c++20|notes={{mark|T is U[]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared( std::size_t N );
 
shared_ptr<T> make_shared( std::size_t N );
 
}}
 
}}
{{dcl | num=3 | since=c++20 | notes={{mark|T is U[N]}}|
+
{{dcl|num=3|since=c++20|notes={{mark|T is U[N]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared();
 
shared_ptr<T> make_shared();
 
}}
 
}}
{{dcl | num=4 | since=c++20 | notes={{mark|T is U[]}}|
+
{{dcl|num=4|since=c++20|notes={{mark|T is U[]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u );
 
shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u );
 
}}
 
}}
{{dcl | num=5 | since=c++20 | notes={{mark|T is U[N]}}|
+
{{dcl|num=5|since=c++20|notes={{mark|T is U[N]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared( const std::remove_extent_t<T>& u );
 
shared_ptr<T> make_shared( const std::remove_extent_t<T>& u );
 
}}
 
}}
{{dcl | num=6 | since=c++20 | notes={{mark|T is not U[]}}|
+
{{dcla|num=6|since=c++20|notes={{mark|T is not U[]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared_for_overwrite();
 
shared_ptr<T> make_shared_for_overwrite();
 
}}
 
}}
{{dcl | num=7 | since=c++20 | notes={{mark|T is U[]}}|
+
{{dcl|num=7|since=c++20|notes={{mark|T is U[]}}|
template<class T>
+
template< class T >
 
shared_ptr<T> make_shared_for_overwrite( std::size_t N );
 
shared_ptr<T> make_shared_for_overwrite( std::size_t N );
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Constructs an object of type {{tt|T}} and wraps it in a {{lc|std::shared_ptr}} using {{tt|args}} as the parameter list for the constructor of {{tt|T}}. The object is constructed as if by the expression {{c|::new (pv) T(std::forward<Args>(args)...)}}, where {{tt|pv}} is an internal {{tt|void*}} pointer to storage suitable to hold an object of type {{tt|T}}. The storage is typically larger than {{tt|sizeof(T)}} in order to use one allocation for both the control block of the shared pointer and the {{tt|T}} object. The {{tt|std::shared_ptr}} constructor called by this function enables {{tt|shared_from_this}} with a pointer to the newly constructed object of type {{tt|T}}. {{cpp/enable_if|T is not an array type}}
+
@1@ Constructs an object of type {{tt|T}} and wraps it in a {{lc|std::shared_ptr}} using {{c|args}} as the parameter list for the constructor of {{tt|T}}. The object is constructed as if by the expression {{c|::new (pv) T(std::forward<Args>(args)...)}}, where {{tt|pv}} is an internal {{c|void*}} pointer to storage suitable to hold an object of type {{tt|T}}. The storage is typically larger than {{c|sizeof(T)}} in order to use one allocation for both the control block of the shared pointer and the {{tt|T}} object. The {{tt|std::shared_ptr}} constructor called by this function enables {{tt|shared_from_this}} with a pointer to the newly constructed object of type {{tt|T}}. {{rrev|since=c++20|{{cpp/enable_if|T is not an array type}}.}}
@2,3@ Same as {{v|1}}, but the object constructed is a possibly-multidimensional array whose non-array elements of type {{tt|std::remove_all_extents_t<T>}} are value-initialized as if by placement-new expression {{c|::new(pv) std::remove_all_extents_t<T>()}}. The overload {{v|2}} creates an array of size {{tt|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.
+
@2,3@ Same as {{v|1}}, but the object constructed is a possibly-multidimensional array whose non-array elements of type {{c|std::remove_all_extents_t<T>}} are value-initialized as if by placement-new expression {{c|::new(pv) std::remove_all_extents_t<T>()}}. The overload {{v|2}} creates an array of size {{c|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.
@4,5@ Same as {{v|2,3}}, but every element is initialized from the default value {{tt|u}}. If {{tt|U}} is not an array type, then this is performed as if by the same placement-new expression as in {{v|1}}; otherwise, this is performed as if by initializing every non-array element of the (possibly multidimensional) array with the corresponding element from {{tt|u}} with the same placement-new expression as in {{v|1}}. The overload {{v|4}} creates an array of size {{tt|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.
+
@4,5@ Same as {{v|2,3}}, but every element is initialized from the default value {{c|u}}. If {{tt|U}} is not an array type, then this is performed as if by the same placement-new expression as in {{v|1}}; otherwise, this is performed as if by initializing every non-array element of the (possibly multidimensional) array with the corresponding element from {{c|u}} with the same placement-new expression as in {{v|1}}. The overload {{v|4}} creates an array of size {{c|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.
@6@ Same as {{v|1}} if {{tt|T}} is not an array type and {{v|3}} if {{tt|T}} is {{tt|U[N]}}, except that the created object is [[cpp/language/default_initialization|default-initialized]].
+
@6@ Same as {{v|1}} if {{tt|T}} is not an array type and {{v|3}} if {{tt|T}} is {{c|U[N]}}, except that the created object is [[cpp/language/default initialization|default-initialized]].
@7@ Same as {{v|2}}, except that the individual array elements are [[cpp/language/default_initialization|default-initialized]].
+
@7@ Same as {{v|2}}, except that the individual array elements are [[cpp/language/default initialization|default-initialized]].
  
 
In each case, the object {{rev inl|since=c++20|(or individual elements if {{tt|T}} is an array type)}} will be destroyed by {{c|p->~X()}}, where {{tt|p}} is a pointer to the object and {{tt|X}} is its type.
 
In each case, the object {{rev inl|since=c++20|(or individual elements if {{tt|T}} is an array type)}} will be destroyed by {{c|p->~X()}}, where {{tt|p}} is a pointer to the object and {{tt|X}} is its type.
Line 43: Line 43:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | args | list of arguments with which an instance of {{tt|T}} will be constructed.}}
+
{{par|args|list of arguments with which an instance of {{tt|T}} will be constructed}}
{{par | N | array size to use}}
+
{{par|N|array size to use}}
{{par | u | the initial value to initialize every element of the array}}
+
{{par|u|the initial value to initialize every element of the array}}
 
{{par end}}
 
{{par end}}
  
Line 56: Line 56:
 
===Notes===
 
===Notes===
 
This function may be used as an alternative to {{c|std::shared_ptr<T>(new T(args...))}}. The trade-offs are:
 
This function may be used as an alternative to {{c|std::shared_ptr<T>(new T(args...))}}. The trade-offs are:
* {{c|std::shared_ptr<T>(new T(args...))}} performs at least two allocations (one for the object {{tt|T}} and one for the control block of the shared pointer), while {{c|std::make_shared<T>}} typically performs only one allocation (the standard recommends, but does not require this; all known implementations do this)
+
* {{c|std::shared_ptr<T>(new T(args...))}} performs at least two allocations (one for the object {{tt|T}} and one for the control block of the shared pointer), while {{c|std::make_shared<T>}} typically performs only one allocation (the standard recommends, but does not require this; all known implementations do this).
* If any {{lc|std::weak_ptr}} references the control block created by {{tt|std::make_shared}} after the lifetime of all shared owners ended, the memory occupied by {{tt|T}} persists until all weak owners get destroyed as well, which may be undesirable if {{tt|sizeof(T)}} is large.
+
* If any {{lc|std::weak_ptr}} references the control block created by {{tt|std::make_shared}} after the lifetime of all shared owners ended, the memory occupied by {{tt|T}} persists until all weak owners get destroyed as well, which may be undesirable if {{c|sizeof(T)}} is large.
 
* {{c|std::shared_ptr<T>(new T(args...))}} may call a non-public constructor of {{tt|T}} if executed in context where it is accessible, while {{tt|std::make_shared}} requires public access to the selected constructor.
 
* {{c|std::shared_ptr<T>(new T(args...))}} may call a non-public constructor of {{tt|T}} if executed in context where it is accessible, while {{tt|std::make_shared}} requires public access to the selected constructor.
 
* Unlike the {{lc|std::shared_ptr}} constructors, {{tt|std::make_shared}} does not allow a custom deleter.
 
* Unlike the {{lc|std::shared_ptr}} constructors, {{tt|std::make_shared}} does not allow a custom deleter.
 
* {{tt|std::make_shared}} uses {{c|::new}}, so if any special behavior has been set up using a class-specific {{ltt|cpp/memory/new/operator_new|operator new}}, it will differ from {{c|std::shared_ptr<T>(new T(args...))}}.
 
* {{tt|std::make_shared}} uses {{c|::new}}, so if any special behavior has been set up using a class-specific {{ltt|cpp/memory/new/operator_new|operator new}}, it will differ from {{c|std::shared_ptr<T>(new T(args...))}}.
{{rrev|until=c++20|* {{lc|std::shared_ptr}} supports array types (as of C++17), but {{tt|std::make_shared}} does not. This functionality is supported by [http://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#make_shared boost::make_shared]
+
{{rrev|until=c++20|* {{lc|std::shared_ptr}} supports array types (as of C++17), but {{tt|std::make_shared}} does not. This functionality is supported by [https://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#make_shared {{tt|boost::make_shared}}].
 
}}
 
}}
{{rrev|until=c++17|* code such as {{c|f(std::shared_ptr<int>(new int(42)), g())}} can cause a memory leak if {{tt|g}} gets called after {{tt|new int(42)}} and throws an exception, while {{c|f(std::make_shared<int>(42), g())}} is safe, since two function calls are [[cpp/language/eval_order|never interleaved]].}}
+
{{rrev|until=c++17|* code such as {{c|f(std::shared_ptr<int>(new int(42)), g())}} can cause a memory leak if {{tt|g}} gets called after {{c|new int(42)}} and throws an exception, while {{c|f(std::make_shared<int>(42), g())}} is safe, since two function calls are [[cpp/language/eval_order|never interleaved]].}}
 
{{cpp/memory/shared_ptr/enabling shared_from_this}}
 
{{cpp/memory/shared_ptr/enabling shared_from_this}}
 +
 +
{{ftm begin|comment=yes|std=yes}}
 +
{{ftm|__cpp_lib_shared_ptr_arrays|Array support of {{ttt|std::make_shared}}; overloads {{v|2-5|2}}|value=201707L|std=C++20}}
 +
{{ftm|__cpp_lib_smart_ptr_for_overwrite|Smart pointer creation with default initialization ({{lc|std::allocate_shared_for_overwrite}}, {{tt|std::make_shared_for_overwrite}}, {{lc|std::make_unique_for_overwrite}}); overloads {{v|6,7|6}}|value=202002L|std=C++20}}
 +
{{ftm end}}
  
 
===Example===
 
===Example===
 
{{example
 
{{example
| code=
+
|code=
 
#include <iostream>
 
#include <iostream>
 
#include <memory>
 
#include <memory>
 
#include <type_traits>
 
#include <type_traits>
 +
#include <vector>
  
 
struct C
 
struct C
 
{
 
{
  C(int i) : i(i) {} //< constructor needed (until C++20)
+
    // constructors needed (until C++20)
  int i;
+
    C(int i) : i(i) {}
 +
    C(int i, float f) : i(i), f(f) {}
 +
    int i;
 +
    float f{};
 
};
 
};
  
 
int main()
 
int main()
 
{
 
{
     auto sp = std::make_shared<C>(12);
+
     // using `auto` for the type of `sp1`
      
+
    auto sp1 = std::make_shared<C>(1); // overload (1)
     static_assert(std::is_same_v<decltype(sp), std::shared_ptr<C>>);
+
     static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>);
      
+
    std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n";
     std::cout << sp->i << '\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=
+
|output=
12
+
sp1->{ i:1, f:0 }
 +
sp2->{ i:2, f:3 }
 
}}
 
}}
  
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/memory/shared_ptr/dsc constructor}}
+
{{dsc inc|cpp/memory/shared_ptr/dsc constructor}}
{{dsc inc | cpp/memory/shared_ptr/dsc allocate_shared}}
+
{{dsc inc|cpp/memory/shared_ptr/dsc allocate_shared}}
{{dsc inc | cpp/memory/unique_ptr/dsc make_unique}}
+
{{dsc inc|cpp/memory/dsc enable_shared_from_this}}
{{dsc inc | cpp/memory/new/dsc operator_new}}
+
{{dsc inc|cpp/memory/unique_ptr/dsc make_unique}}
 +
{{dsc inc|cpp/memory/new/dsc operator_new}}
 
{{dsc end}}
 
{{dsc end}}
  
[[de:cpp/memory/shared ptr/make shared]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
[[es:cpp/memory/shared ptr/make shared]]
+
[[fr:cpp/memory/shared ptr/make shared]]
+
[[it:cpp/memory/shared ptr/make shared]]
+
[[ja:cpp/memory/shared ptr/make shared]]
+
[[pt:cpp/memory/shared ptr/make shared]]
+
[[ru:cpp/memory/shared ptr/make shared]]
+
[[zh:cpp/memory/shared ptr/make shared]]
+

Latest revision as of 10:13, 20 June 2023

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
 
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[])
1) Constructs an object of type 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)
2,3) Same as (1), but the object constructed is a possibly-multidimensional array whose non-array elements of type 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.
4,5) Same as (2,3), but every element is initialized from the default value 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.
6) Same as (1) if T is not an array type and (3) if T is U[N], except that the created object is default-initialized.
7) Same as (2), except that the individual array elements are 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.

Contents

[edit] 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

[edit] Return value

std::shared_ptr of an instance of type T.

[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

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 by T 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, while std::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)
  • code such as f(std::shared_ptr<int>(new int(42)), g()) can cause a memory leak if g gets called after new int(42) and throws an exception, while f(std::make_shared<int>(42), g()) is safe, since two function calls are never interleaved.
(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] See also

constructs new shared_ptr
(public member function) [edit]
creates a shared pointer that manages a new object allocated using an allocator
(function template) [edit]
allows an object to create a shared_ptr referring to itself
(class template) [edit]
creates a unique pointer that manages a new object
(function template) [edit]
allocation functions
(function) [edit]