命名空间
变体
操作

std::allocate_shared, std::allocate_shared_for_overwrite

来自 cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
实用程序库
语言支持
类型支持 (基本类型,RTTI)
库特性测试宏 (C++20)
动态内存管理
程序实用程序
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三方比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用实用程序
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
动态内存管理
未初始化内存算法
受限的未初始化内存算法
分配器
垃圾回收支持
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)



 
 
在头文件 <memory> 中定义
template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );
(1) (自 C++11 起)
(T 不是数组)
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc, std::size_t N );
(2) (自 C++20 起)
(T 是 U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared( const Alloc& alloc );
(3) (自 C++20 起)
(T 是 U[N])
template< class T, class Alloc >

shared_ptr<T> allocate_shared( const Alloc& alloc, std::size_t N,

                               const std::remove_extent_t<T>& u );
(4) (自 C++20 起)
(T 是 U[])
template< class T, class Alloc >

shared_ptr<T> allocate_shared( const Alloc& alloc,

                               const std::remove_extent_t<T>& u );
(5) (自 C++20 起)
(T 是 U[N])
template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc );
(6) (自 C++20 起)
(T 不是 U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared_for_overwrite( const Alloc& alloc, std::size_t N );
(7) (自 C++20 起)
(T 是 U[])
1) 使用 args 作为 T 构造函数的参数列表,构造一个类型为 T 的对象,并使用 std::shared_ptr 将其包装起来。 对象的构造方式与表达式 ::new (pv) T(v)(直到 C++20)std::allocator_traits<A2>::construct(a, pv, v)(自 C++20 起) 相同,其中 pv 是一个指向存储的内部 void* 指针,该存储适合保存类型为 T 的对象,而 a 是一个绑定到 std::remove_cv_t<T> 的分配器的副本。 存储通常比 sizeof(T) 大,以便为共享指针的控制块和 T 对象使用一次分配。 此函数调用的 std::shared_ptr 构造函数使用指向新构造的类型为 T 的对象的指针启用 shared_from_this。 所有内存分配都是使用 alloc 的副本完成的,该副本必须满足 Allocator 要求。 只有当 T 不是数组类型时,此重载才参与重载解析。
2,3)(1) 相同,但构造的对象是一个可能的多维数组,其每个非数组元素的初始化方式与表达式 std::allocator_traits<A2>::construct(a2, pv) 相同,其中类型为 A2a2 是绑定到管理类型为 std::remove_cv_t<std::remove_all_extents_t<T>> 的对象的分配器的副本。 重载 (2) 创建一个沿其第一维大小为 N 的数组。 数组元素按其地址的升序进行初始化,当其生命周期结束时,按其原始构造的相反顺序进行销毁。
4,5)(2,3) 相同,但数组的元素从默认值 u 初始化。 如果 std::remove_extent_t<T> 本身不是数组类型,则这就像使用与 (1) 中相同的分配器表达式一样执行,只是分配器被绑定到 std::remove_cv_t<std::remove_all_extents_t<T>>。 否则,就像使用来自 u 的相应元素初始化(可能多维的)数组的每个非数组元素一样执行,使用与 (1) 中相同的分配器表达式,只是分配器被绑定到类型 std::remove_cv_t<std::remove_all_extents_t<T>>。 重载 (4) 创建一个沿第一维大小为 N 的数组。 数组元素按其地址的升序进行初始化,当其生命周期结束时,按其原始构造的相反顺序进行销毁。
6) 如果 T 不是数组类型,则与 (1) 相同;如果 TU[N],则与 (3) 相同,只是创建的对象是 默认初始化 的。
7)(2) 相同,只是数组的各个元素是 默认初始化 的。

对于 allocate_shared,对象 (或 (2-5) 的各个数组元素)(自 C++20 起) 通过表达式 std::allocator_traits<A2>::destroy(a, p) 销毁,其中 p 是指向对象的指针,而 a 是传递给 allocate_shared 的分配器的副本,绑定到要销毁的对象的类型。

对于 allocate_shared_for_overwrite,对象(如果 T 是数组类型,则为各个元素)将通过 p->~X() 销毁,其中 p 是指向对象的指针,而 X 是其类型。

(自 C++20 起)

内容

[edit] 参数

alloc - 要使用的 Allocator
args... - 用于构造 T 实例的参数列表
N - 要使用的数组大小
u - 用于初始化数组每个元素的初始值

[edit] 返回值

类型为 T 的实例的 std::shared_ptr

[edit] 异常

可能会抛出从 Alloc::allocate() 或从 T 的构造函数抛出的异常。 如果抛出异常,(1) 将不起作用。 如果在数组的构造期间抛出异常,则已初始化的元素将按相反顺序销毁(自 C++20 起).

[edit] 注意

std::make_shared 一样,此函数通常只执行一次分配,并将 T 对象和控制块放在分配的内存块中(标准建议但不要求这样做,所有已知实现都这样做)。 alloc 的副本存储为控制块的一部分,以便在共享和弱引用计数都达到零时可以使用它来释放它。

std::shared_ptr构造函数 不同,std::allocate_shared 不接受单独的自定义删除器:提供的分配器用于销毁控制块和 T 对象,以及用于释放其共享内存块。

std::shared_ptr 支持数组类型(自 C++17 起),但 std::allocate_shared 不支持。 此功能由 boost::allocate_shared 支持。

(直到 C++20)

构造函数使用类型为 U* 的指针 启用 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_thisstd::enable_shared_from_this 的隐藏可变 std::weak_ptr 成员。 对 weak_this 成员的赋值不是原子性的,并且与对同一对象的任何潜在并发访问冲突。 这确保将来对 shared_from_this() 的调用将与由此原始指针构造函数创建的 std::shared_ptr 共享所有权。

上面的描述性代码中的测试 ptr->weak_this.expired() 确保如果 weak_this 已经指示了一个所有者,则不会重新分配 weak_this。 此测试是自 C++17 起必需的。

功能测试 Std 功能
__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)

[edit] 示例

#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

[edit] 另请参阅

构造新的 shared_ptr
(公有成员函数) [edit]
创建一个管理新对象的共享指针
(函数模板) [编辑]