make_unique的例外情况:为什么f(new T)异常是安全的

ted*_*ted 2 c++ exception exception-safety c++14

我一直在阅读GOTW102,并且想知道为什么make_unique比其他情况更安全,或者为什么f(new T(...))比例更安全f(new T1(...), new T2(...)).

make_unique博客的实施内容如下:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
Run Code Online (Sandbox Code Playgroud)

现在我想知道是否f(new T(...))一般异常安全(无泄漏),或者如果它只是异常安全的情况下,make_unique因为增加的知识,建设者std::unique_ptr不扔?(T根据我的理解,如果新建的话会被泄露.

Bil*_*eal 10

原因是在函数调用或类似函数中,参数不会引发序列点(不是"之前排序").例如:

do_work(unique_ptr<A>(new A), unique_ptr<B>(new B));
Run Code Online (Sandbox Code Playgroud)

允许编译器生成如下代码:

  1. new A
  2. new B //可能会扔!
  3. 构造 unique_ptr<A>
  4. 构造 unique_ptr<B>
  5. 呼叫 do_work

如果new B抛出,那么你已经泄露了A,因为没有unique_ptr被建造.

unique_ptr构造放入其自己的函数中可以消除这个问题,因为不允许编译器同时执行函数体(因此"新"和"构造unique_ptr步骤需要一起完成").


那是,给定:

do_work(make_unique<A>(), make_unique<B>())
Run Code Online (Sandbox Code Playgroud)

编译器必须生成如下代码:

  1. 呼叫 make_unique<A>
  2. 呼叫 make_unique<B>
  3. 呼叫 do_work

要么

  1. 呼叫 make_unique<B>
  2. 呼叫 make_unique<A>
  3. 呼叫 do_work

在新的物体漂浮而不拥有unique_ptr不可能的情况下进行泄漏.

  • @ted:你得到了保证,因为C++ 11 20.7.1.2 [unique.ptr.single]/1:`// 20.7.1.2.1,constructors [...]显式unique_ptr(指针p)noexcept;`< - 声明`noexcept` (3认同)