std :: shared_ptr例外安全

Arn*_*aud 30 c++ memory-leaks shared-ptr c++11

我刚刚意识到阅读这个页面,std :: shared_ptr的构造函数与单个指针参数不是noexcept.

因此,以下代码包含可能的内存泄漏:

std::shared_ptr<int> p3 (new int);
Run Code Online (Sandbox Code Playgroud)

原因是可能发生两次分配:

  • 在调用构造函数之前的第一个
  • shared_ptr构造函数中的第二个(例如VS 2012中发生的情况)

这里有两个问题:

如果第二个分配抛出异常,第一个分配的内存泄漏,这是真的吗?

如果答案是肯定的:

使用std :: shared_ptr的正确习惯用法是什么?

  • 使用make_shared
  • 将第一个分配的所有权赋予std :: unique_ptr然后转移所有权
  • 其他想法 ?

Igo*_*nik 29

template<class Y> explicit shared_ptr(Y* p);
Run Code Online (Sandbox Code Playgroud)

[util.smartptr.shared.const]/6 当无法获取内存以外的资源时,抛出:bad_alloc或实现定义的异常.
[util.smartptr.shared.const]/7 异常安全:如果抛出异常,delete p则调用.

所以不,没有内存泄漏.


Tho*_*ire 11

迟到的答案,但最好make_shared()用于异常安全,如 GotW#102中所述:以下代码不是异常安全的:

 f( std::shared_ptr<T1>{ new T1 }, std::shared_ptr<T2>{ new T2 } );
Run Code Online (Sandbox Code Playgroud)

以下是:

f( std::make_shared<T1>(), std::make_shared<T2>() );
Run Code Online (Sandbox Code Playgroud)

  • 另一种情况,您可能**不想**想要使用 std::make_shared&lt;T&gt;() :如果从使用 std::make_shared&lt;T&gt;() 生成的shared_ptr 获得比shared_ptr 寿命更长的weak_ptr,**对象 T 占用的内存将持续存在,直到所有弱所有者也被销毁**。(为什么? std::make_shared 在实践中比 shared_ptr 构造函数更高效,因为它只为对象 T 和控制块进行一次分配,而不是两次。weak_ptr 需要控制块,所以你就陷入了这个整体块。) (4认同)