std::allocate_shared, std::allocate_shared_default_init

来自cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
 
动态内存管理
未初始化存储
(C++17)
垃圾收集支持
杂项
(C++20)
(C++11)
(C++11)
C 库
低层内存管理
 
 
定义于头文件 <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_default_init( const Alloc& alloc );
(6) (C++20 起)
(T 非 U[])
template< class T, class Alloc >
shared_ptr<T> allocate_shared_default_init( const Alloc& alloc, std::size_t N );
(7) (C++20 起)
(T 为 U[])
1)argsT 的构造函数参数列表,构造 T 类型对象并将它包装于 std::shared_ptr 。对象如同以表达式 ::new (pv) T(v) (C++20 前)std::allocator_traits<A2>::construct(a, pv, v) (C++20 起) 构造,其中 pv 是内部指向适合保有 T 类型对象的存储的 void* 指针,而 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) 初始化,其中 A2 类型的 a2 是重绑定为管理 std::remove_cv_t<std::remove_all_extents_t<T>> 类型对象的分配器副本。重载 (2) 创建第一维上大小为 N 的数组。数组元素以其地址递增顺序初始化,而当其生存期结束时,以原本构造顺序的逆序销毁。
4,5)(2,3) ,但每个元素从默认值 u 初始化。若 U 不是数组类型,则这如同以与 (1) 中相同的分配器表达式进行,除了把分配器重绑定到 std::remove_cv_t<std::remove_all_extents_t<T>> 。否则,这如同以如同 (1) 中的分配器表达式,从来自 u 的对应元素初始化(可能多维的)数组的每个非数组元素,除了重绑定分配器到 std::remove_cv_t<std::remove_all_extents_t<T>> 类型。重载 (4)创建第一维上大小为 N 的数组。数组元素以其地址递增顺序初始化,而当其生存期结束时,以原本构造顺序的逆序销毁。
6)T 非数组类型则同 (1) 而若 TU[N] 则同 (3) ,除了默认初始化创建的元素。
7)(2) ,除了默认初始化单独的数组元素。

对于 allocate_shared ,通过表达式 std::allocator_traits<A2>::destroy(a, p) 销毁对象{{rev inl|since=c++20|(或对于 (2-5) 为单独的数组元素),其中 p 是指向对象的指针而 a 是传递给 allocate_shared 的分配器副本,重绑定到正在销毁的对象类型。

对于 allocate_shared_default_init ,对象(或若 T 为数组类型则为单独的数组元素)将会被 p->~X() 销毁,其中 p 是指向对象的指针而 X 是对象的类型。

(C++20 起)

参数

alloc - 使用的分配器 (Allocator)
args... - 构造 T 示例将要用到的参数列表。
N - 所用的数组大小
u - 初始化数组每个元素的初值

返回值

T 类型实例的的 std::shared_ptr

异常

能抛出从 Alloc::allocate() 抛出的异常,或从 T 构造函数抛出的异常。若抛出异常,则 (1) 无效果。若异常在数组的构造中抛出,则已初始化元素以逆序销毁。 (C++20 起)

注意

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

上述解释代码中,测试 ptr->weak_this.expired() 是为确保若 weak_this 指示已有占有者则重赋值它。从 C++17 起要求此测试。

参阅

构造新的 shared_ptr
(公开成员函数)
创建管理一个新对象的共享指针
(函数模板)