std:: make_shared, std:: make_shared_for_overwrite
|
定义于头文件
<memory>
|
||
|
template
<
class
T,
class
...
Args
>
shared_ptr < T > make_shared ( Args && ... args ) ; |
(1) | (C++11 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N ) ; |
(2) | (C++20 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( ) ; |
(3) | (C++20 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N, const std:: remove_extent_t < T > & u ) ; |
(4) | (C++20 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( const std:: remove_extent_t < T > & u ) ; |
(5) | (C++20 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( ) ; |
(6) | (C++20 起) |
|
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( std:: size_t N ) ; |
(7) | (C++20 起) |
为对象分配内存并使用提供的参数初始化该对象。返回一个管理新创建对象的 std::shared_ptr 对象。
T
,其构造方式相当于执行
::
new
(
pv
)
T
(
std::
forward
<
Args
>
(
args
)
...
)
,其中
pv
是指向能容纳
T
类型对象的存储空间的
void
*
类型指针。若需销毁该对象,则销毁方式相当于执行
pt
-
>
~T
(
)
,其中
pt
是指向该
T
类型对象的指针。
|
此重载仅当
|
(C++20 起) |
T
为无边界数组类型时,此重载才会参与重载决议。
T
。每个元素都具有默认初始值。
T
为有界数组类型时,此重载参与重载决议。
T
为无边界数组类型时,此重载才会参与重载决议。
T
。每个元素具有初始值
u
。
T
为有界数组类型时,此重载参与重载决议。
T
。
-
若
T不是数组类型,该对象将以 :: new ( pv ) T 的方式构造,其中 pv 是指向能容纳T类型对象的存储空间的 void * 指针。若需销毁该对象,将以 pt - > ~T ( ) 的方式销毁,其中 pt 是指向该T类型对象的指针。 -
若
T是有界数组类型,每个元素的初始值未指定。
T
不是数组类型或为有界数组类型时,此重载才会参与重载决议。
T
为无边界数组类型时,此重载才会参与重载决议。
数组元素的初始化与销毁
类型为
2,3)
::
new
(
pv
)
U
(
)
4,5)
::
new
(
pv
)
U
(
u
)
6,7)
::
new
(
pv
)
U
当返回的 std::shared_ptr 所管理对象的生命周期结束时,或当数组元素的初始化抛出异常时,已初始化的元素将按其原始构造顺序的逆序进行销毁。
对于每个待销毁的非数组类型
|
(since C++20) |
参数
| args | - |
用于构造
T
类型对象的参数列表
|
| N | - | 要使用的数组大小 |
| u | - | 用于初始化数组每个元素的初始值 |
返回值
指向
T
类型对象的
std::shared_ptr
,或者指向
std::
remove_extent_t
<
T
>
[
N
]
如果
T
是无边界数组类型
(C++20 起)
。
对于返回的 std::shared_ptr r , r. get ( ) 返回非空指针且 r. use_count ( ) 返回 1 。
异常
可能抛出
std::bad_alloc
或
T
的构造函数抛出的任何异常。若抛出异常,则函数无效果。
若在数组构造期间抛出异常,则以逆序销毁已初始化的元素。
(C++20 起)
注释
这些函数通常会分配比 sizeof ( T ) 更多的内存,以便为内部簿记结构(如引用计数)预留空间。
这些函数可作为 std:: shared_ptr < T > ( new T ( args... ) ) 的替代方案。其权衡因素为:
-
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
至少执行两次内存分配(一次为对象
T,一次为共享指针的控制块),而 std :: make_shared < T > 通常仅执行一次分配(标准建议但不强制要求此行为;所有已知实现均满足此特性)。 -
若存在
std::weak_ptr
在所有共享所有者生命周期结束后仍引用由
std::make_shared创建的控制块,则T占用的内存会持续存在直至所有弱所有者也被销毁,当 sizeof ( T ) 较大时可能产生不利影响。 -
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
在可访问的上下文中执行时可能调用
T的非公开构造函数,而std::make_shared要求对所选构造函数具有公开访问权限。 -
与
std::shared_ptr
构造函数不同,
std::make_shared不允许使用自定义删除器。 -
std::make_shared使用 :: new ,因此若通过类特定的 operator new 设置了任何特殊行为,其表现将与 std:: shared_ptr < T > ( new T ( args... ) ) 存在差异。
|
(直至 C++20) |
|
(C++17 前) |
构造函数通过类型为
U*
的指针
ptr
启用
shared_from_this
意味着:它会判断
U
是否存在一个
明确且可访问的
(C++17 起)
基类,且该基类是
std::enable_shared_from_this
的特化;若存在,则构造函数会执行以下表达式:
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
)
)
;
。
对
weak_this
的赋值操作不是原子性的,会与同一对象可能存在的并发访问产生冲突。这确保了后续对
shared_from_this()
的调用能够与通过此裸指针构造函数创建的
std::shared_ptr
共享所有权。
测试
ptr
-
>
weak_this
.
expired
(
)
确保当
weak_this
已指向持有者时不会被重新赋值。该测试自 C++17 起成为必需。
| 功能测试 宏 | 值 | 标准 | 功能 |
|---|---|---|---|
__cpp_lib_shared_ptr_arrays
|
201707L
|
(C++20) |
std::make_shared
的数组支持;重载版本
(
2-5
)
|
__cpp_lib_smart_ptr_for_overwrite
|
202002L
|
(C++20) |
使用默认初始化的智能指针创建(
std::allocate_shared_for_overwrite
,
std::make_shared_for_overwrite
,
std::make_unique_for_overwrite
);重载版本
(
6,7
)
|
示例
#include <iostream> #include <memory> #include <type_traits> #include <vector> struct C { // 需要构造函数(直至 C++20) C(int i) : i(i) {} C(int i, float f) : i(i), f(f) {} int i; float f{}; }; int main() { // 对“sp1”类型使用“auto” auto sp1 = std::make_shared<C>(1); // 重载 (1) static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>); std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n"; // 显式指定“sp2”的类型 std::shared_ptr<C> sp2 = std::make_shared<C>(2, 3.0f); // 重载 (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"; // 指向值初始化的 float[64] 的 shared_ptr;重载 (2): std::shared_ptr<float[]> sp3 = std::make_shared<float[]>(64); // 指向值初始化的 long[5][3][4] 的 shared_ptr;重载 (2): std::shared_ptr<long[][3][4]> sp4 = std::make_shared<long[][3][4]>(5); // 指向值初始化的 short[128] 的 shared_ptr;重载 (3): std::shared_ptr<short[128]> sp5 = std::make_shared<short[128]>(); // 指向值初始化的 int[7][6][5] 的 shared_ptr;重载 (3): std::shared_ptr<int[7][6][5]> sp6 = std::make_shared<int[7][6][5]>(); // 指向 double[256] 的 shared_ptr,其中每个元素为 2.0;重载 (4): std::shared_ptr<double[]> sp7 = std::make_shared<double[]>(256, 2.0); // 指向 double[7][2] 的 shared_ptr,其中每个 double[2] // 元素为 {3.0, 4.0};重载 (4): std::shared_ptr<double[][2]> sp8 = std::make_shared<double[][2]>(7, {3.0, 4.0}); // 指向 vector<int>[4] 的 shared_ptr,其中每个 vector // 包含内容 {5, 6};重载 (4): std::shared_ptr<std::vector<int>[]> sp9 = std::make_shared<std::vector<int>[]>(4, {5, 6}); // 指向 float[512] 的 shared_ptr,其中每个元素为 1.0;重载 (5): std::shared_ptr<float[512]
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
| DR | 适用范围 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| LWG 4024 | C++20 |
不清楚在
std::make_shared_for_overwrite
中构造的对象如何被销毁
|
已明确说明 |
参见
构造新的
shared_ptr
(公开成员函数) |
|
|
创建管理使用分配器分配的新对象的共享指针
(函数模板) |
|
|
(C++11)
|
允许对象创建指向自身的
shared_ptr
(类模板) |
|
(C++14)
(C++20)
|
创建管理新对象的唯一指针
(函数模板) |
|
分配函数
(函数) |