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 的潜在重绑副本。
此重载只有在 |
(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 | - | 用以初始化数组每个元素的初值 |
[编辑] 返回值
指向具有 T
类型或在 T
是无边界的数组类型时具有 std::remove_extent_t<T>[N] 类型(C++20 起)的对象的 std::shared_ptr。
对于返回的 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
构造函数
,std::allocate_shared
不接受另外的自定义删除器:它用提供的分配器来进行控制块和 T
对象的析构,及其共享内存块的解分配。
std::shared_ptr 支持数组类型(从 C++17 起),但 |
(C++20 前) |
构造函数以 U*
类型指针 ptr 启用 shared_from_this
,表示它确定 U
是否拥有作为 std::enable_shared_from_this 特化的无歧义且可访问(C++17 起)基类,在是的情况下会求值
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(); } //< 全部共享指针都会在离开作用域使自动清理。
输出:
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 (公开成员函数) | |
创建管理一个新对象的共享指针 (函数模板) |