使用make_shared时会发生什么

Tra*_*cer 26 c++ smart-pointers make-shared c++11

我感兴趣的是这两行代码是否相同:

shared_ptr<int> sp(new int(1)); // double allocation?
shared_ptr<int> sp(make_shared<int>(1)); // just one allocation?
Run Code Online (Sandbox Code Playgroud)

如果这是真的,有人可以解释为什么在第二行只有一个分配?

Sha*_*our 33

第一种情况下不执行双重分配,它执行两个分配,一个用于管理对象和一个用于控制块shared_ptr.

对于第二种情况,cppreference有一个很好的解释为什么std :: make_shared 通常只执行一个内存分配(强调我的前进):

此函数通常使用单个内存分配为T对象和shared_ptr的控制块分配内存(它是标准中的非绑定要求).相反,声明std :: shared_ptr p(new T(Args ...))执行至少两次内存分配,这可能会产生不必要的开销.

并从std :: shared_ptr部分说:

当通过调用std :: make_shared或std :: allocate_shared创建shared_ptr时,将使用单个分配创建控制块和托管对象的内存.托管对象在控制块的数据成员中就地构造.当通过其中一个shared_ptr构造函数创建shared_ptr时,必须单独分配托管对象和控制块.在这种情况下,控制块存储指向被管理对象的指针.

make_shared描述与C++ 11草案标准一致,该标准shared_ptr创建部分中说明20.7.2.2.6

template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
  shared_ptr<T> allocate_shared(const A& a, Args&&... args);
Run Code Online (Sandbox Code Playgroud)

[...]

备注:实现应该只执行一次内存分配.[注意:这提供的效率相当于侵入式智能指针. - 尾注]

[注意:这些函数通常会分配比sizeof(T)更多的内存,以允许内部簿记结构,例如引用计数. - 尾注]

Herb Sutter make_sharedGotW#89解决方案中使用的优势有更详细的解释:智能指针并指出了一些优点:

  • 它减少了分配开销
  • 它改善了地方.
  • 避免一个明确的新.
  • 避免异常安全问题.

请注意,使用make_shared使用std :: weak_ptr时 有一些缺点.


Alp*_*per 5

节中cppreference std::shared_ptr的解释Implementation notes

在典型的实现中,std::shared_ptr 仅保存两个指针:

  1. 指向被管理对象的指针
  2. 指向控制块的指针

当通过调用 std::make_shared 或 std::allocate_shared 创建shared_ptr时,控制块和托管对象的内存都是通过单个分配创建的。管理对象在控制块的数据成员中就地构建。当通过shared_ptr构造函数之一创建shared_ptr时,必须单独分配托管对象和控制块。在这种情况下,控制块存储指向被管理对象的指针。