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 是一个 void* 指针,指向足以容纳T
类型对象的存储。如果要销毁该对象,则其销毁方式如同 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 | - | 要使用的分配器 (Allocator) |
args... | - | 用于构造 T 实例的参数列表 |
N | - | 要使用的数组大小 |
u | - | 用于初始化数组中每个元素的初始值 |
[编辑] 返回值
指向 T
类型对象的 std::shared_ptr,若 T
为无界数组类型,则为 std::remove_extent_t<T>[N](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
的构造函数
不同,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() { // Create a polymorphic allocator using the monotonic buffer resource 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) // Use std::allocate_shared with the custom allocator v.emplace_back(std::allocate_shared<Value>(allocator, i)); for (const auto& sp : v) sp->print(); } //< All shared pointers will automatically clean up when they go out of scope.
输出
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 (公开成员函数) | |
(C++20 起) |
创建一个管理新对象的共享指针 (函数模板) |