std::make_shared

来自cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
 
 
 
定义于头文件 <memory>
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
(1) (C++11 起)
(T 非数组)
template<class T>
shared_ptr<T> make_shared(std::size_t N);
(2) (C++20 起)
(T 为 U[])
template<class T>
shared_ptr<T> make_shared();
(3) (C++20 起)
(T 为 U[N])
template<class T>
shared_ptr<T> make_shared(std::size_t N, const std::remove_extent_t<T>& u);
(4) (C++20 起)
(T 为 U[])
template<class T>
shared_ptr<T> make_shared(const std::remove_extent_t<T>& u);
(5) (C++20 起)
(T 为 U[N])
1)argsT 的构造函数参数列表,构造 T 类型对象并将它包装于 std::shared_ptr 。对象如同用表达式 ::new (pv) T(std::forward<Args>(args)...) 构造,其中 pv 是内部指向适合保有 T 类型对象的存储的 void* 指针。存储典型地大于 sizeof(T) ,以对共享指针控制块和 T 对象使用一次分配。此函数所调用的 std::shared_ptr 构造函数以指向新构造的 T 类型对象指针启用 shared_from_this 。此重载仅当 T 不是数组类型才参与重载决议。
2,3)(1) ,但构造的元素是可能多维的数组,其 std::remove_all_extents_t<T> 类型的非数组元素如同以布置 new 表达式 ::new(pv) std::remove_all_extents_t<T>() 值初始化。重载 (2) 创建第一维上大小为 N 的数组。数组元素以其地址递增顺序初始化。
4,5)(2,3) ,但每个元素从默认值 u 初始化。若 U 不是数组类型,则这如同以如 (1) 中的布置 new 表达式进行;否则,这如同以如同 (1) 中的布置 new 表达式,从来自 u 的对应元素初始化(可能多维的)数组的每个非数组元素。重载 (4) 创建第一维上大小为 N 的数组。数组元素以其地址递增顺序初始化。

目录

[编辑] 参数

args - 将用以构造 T 实例的参数列表。
N - 要使用的数组
u - 初始化数组每个元素的初值

[编辑] 返回值

类型 T 实例的 std::shared_ptr

[编辑] 异常

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

[编辑] 注意

此函数可用作 std::shared_ptr<T>(new T(args...)) 的替代品。得失是:

  • std::shared_ptr<T>(new T(args...)) 进行至少二次分配(一次为 T 而另一次为共享指针的控制块),而 std::make_shared<T> 典型地仅进行一次分配(标准推荐但不要求如此,所有已知实现均如此)。
  • 若任何 std::weak_ptr 在所有共享拥有者的生存期结束后引用 std::make_shared 所创建的控制块,则 T 所占有的内存维持着,直至所有弱拥有者亦被销毁,若 sizeof(T) 较大则这可能是不想要的。
  • std::shared_ptr<T>(new T(args...)) 可能调用 T 的非公开构造函数,若在它可访问的语境中执行,而 std::make_shared 要求对被选择构造函数的公开访问。
  • 不同于 std::shared_ptr 构造函数, std::make_shared 不允许自定义删除器。
  • std::shared_ptr 支持数组类型(从 C++17 起),但 std::make_shared 不支持。此功能为 boost::make_shared 所支持。
(C++20 前)
  • f(std::shared_ptr<int>(new int(42)), g()) 的代码可能导致内存泄漏,若 gnew int(42) 后得到调用且抛出异常,而 f(std::make_shared<int>(42), g()) 是安全的,因为二个函数调用决不会穿插
(C++17 前)

构造函数以 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 起要求此测试。

[编辑] 示例

#include <iostream>
#include <memory>
 
void foo(const std::shared_ptr<int>& i)
{
    (*i)++;
}
 
int main()
{
    auto sp = std::make_shared<int>(12);
    foo(sp);
    std::cout << *sp << '\n';
}

输出:

13

[编辑] 参阅

构造新的 shared_ptr
(公开成员函数) [编辑]
创建一个共享指针来管理使用分配器分配的新对象
(函数模板) [编辑]
创建管理对象的唯一指针
(函数模板) [编辑]