std:: allocate_shared, std:: allocate_shared_for_overwrite
|
定义于头文件
<memory>
|
||
|
template
<
class
T,
class
Alloc,
class
...
Args
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, Args && ... args ) ; |
(1) | (C++11 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ; |
(2) | (C++20 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ; |
(3) | (C++20 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
std::
size_t
N,
|
(4) | (C++20 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
|
(5) | (C++20 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ; |
(6) | (C++20 起) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared_for_overwrite
(
const
Alloc
&
alloc,
|
(7) | (C++20 起) |
使用
alloc
的副本(为未指定的
value_type
重新绑定)为对象分配内存,并使用提供的参数初始化该对象。返回管理新创建对象的
std::shared_ptr
对象。
T
,其构造方式如同通过
std::
allocator_traits
<
Alloc
>
::
construct
( a, pt, ( std:: forward < Args > ( args ) ... ) 进行构造,其中 pt 是指向能容纳 std:: remove_cv_t < T > 类型对象的存储空间的 std:: remove_cv_t < T > * 类型指针。若需销毁该对象,则销毁方式如同通过 std:: allocator_traits < Alloc > :: destroy ( a, pt ) 进行销毁,其中 pt 是指向该 std:: remove_cv_t < T > 类型对象的指针。
Alloc
,它是
alloc
经可能重新绑定后的副本。
|
此重载仅当
|
(since C++20) |
T
为无边界数组类型时,此重载才会参与重载决议。
T
。每个元素都具有默认初始值。
T
为有界数组类型时,此重载才会参与重载决议。
T
为无边界数组类型时,此重载才会参与重载决议。
T
。每个元素具有初始值
u
。
T
为有界数组类型时,此重载参与重载决议。
T
。
-
若
T不是数组类型,对象将以 :: new ( pv ) T 的方式构造,其中 pv 是指向能容纳T类型对象的存储空间的 void * 指针。若需销毁该对象,将以 pt - > ~T ( ) 的方式销毁,其中 pt 是指向该T类型对象的指针。 -
若
T是有界数组类型,每个元素的初始值未指定。
T
不是数组类型或为有界数组类型时,此重载才会参与重载决议。
T
为无边界数组类型时,此重载才会参与重载决议。
数组元素的初始化与销毁
在以下描述中,
a
的类型为
类型为
2,3)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu
)
4,5)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu, u
)
6,7)
::
new
(
pv
)
U
当返回的 std::shared_ptr 所管理对象的生命周期结束时,或当数组元素的初始化抛出异常时,已初始化的元素按其原始构造顺序的逆序进行销毁。
对于每个待销毁的非数组类型
6,7)
pu
-
>
~U
(
)
,其中
pu
是指向该
U
类型数组元素的指针
|
(自 C++20 起) |
参数
| alloc | - | 使用的 分配器 |
| args... | - |
用于构造
T
实例的参数列表
|
| N | - | 使用的数组大小 |
| u | - | 用于初始化数组每个元素的初始值 |
返回值
std::shared_ptr
指向类型为
T
的对象
或
std::
remove_extent_t
<
T
>
[
N
]
若
T
为无边界数组类型
(C++20 起)
。
对于返回的 std::shared_ptr r , r. get ( ) 返回非空指针且 r. use_count ( ) 返回 1 。
异常
可能抛出由
Alloc
::
allocate
(
)
或
T
的构造函数所抛出的异常。若抛出异常,则
(1)
不产生任何效果。
若在数组构造过程中抛出异常,则以逆序销毁已初始化的元素
(C++20 起)
。
注释
这些函数通常会分配比 sizeof ( T ) 更多的内存,以便为内部簿记结构(如引用计数)预留空间。
与
std::make_shared
类似,此函数通常仅执行一次内存分配,并将
T
对象与控制块共同置于分配的内存块中(标准建议但不强制要求此行为,目前所有已知实现均采用此方式)。存储
alloc
的副本作为控制块的一部分,以便在共享引用计数和弱引用计数均归零时用于释放内存。
与
std::shared_ptr
的
constructors
不同,
std::allocate_shared
不接受单独的自定义删除器:提供的分配器既用于控制块和
T
对象的销毁,也用于其共享内存块的释放。
|
std::shared_ptr
支持数组类型(自 C++17 起),但
|
(C++20 前) |
构造函数通过类型为
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_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 <cstddef> #include <iostream> #include <memory> #include <memory_resource> #include <vector> class Value { int i; public: Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; } ~Value() { std::cout << "~Value(), i = " << i << '\n'; } void print() const { std::cout << "i = " << i << '\n'; } }; int main() { // 使用单调缓冲区资源创建多态分配器 std::byte buffer[sizeof(Value) * 8]; std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer)); std::pmr::polymorphic_allocator<Value> allocator(&resource); std::vector<std::shared_ptr<Value>> v; for (int i{}; i != 4; ++i) // 使用 std::allocate_shared 配合自定义分配器 v.emplace_back(std::allocate_shared<Value>(allocator, i)); for (const auto& sp : v) sp->print(); } //< 所有 shared_ptr 在超出作用域时将自动清理
输出:
Value(), i = 0 Value(), i = 1 Value(), i = 2 Value(), i = 3 i = 0 i = 1 i = 2 i = 3 ~Value(), i = 0 ~Value(), i = 1 ~Value(), i = 2 ~Value(), i = 3
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| LWG 3216 | C++20 |
std::allocate_shared
总是在构造和销毁对象前
重新绑定分配器 |
重新绑定为可选操作 |
| LWG 4024 | C++20 |
未明确说明在
std::allocate_shared_for_overwrite
中构造的对象如何被销毁 |
已明确说明 |
参见
构造新的
shared_ptr
(公开成员函数) |
|
|
创建管理新对象的共享指针
(函数模板) |