make_unique 的异常安全:为什么 f(new T) 异常安全
Exceptionsafety of make_unique: Why is f(new T) exception safe
我一直在阅读 GOTW102,想知道为什么 make_unique
比其他情况更安全,或者为什么 f(new T(...))
比 [=14] 更安全=].
博客中的 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)... ) );
}
现在我想知道 f(new T(...))
是否在一般情况下是异常安全的(无泄漏),或者它是否只是在 make_unique
的情况下是异常安全的,因为增加的知识是 std::unique_ptr
不扔? (因为如果这样的话,根据我的理解,新构建的 T
无论如何都会被泄露。
原因是在函数调用或类似的调用中,参数不包含序列点(不是 "sequenced before")。例如:
do_work(unique_ptr<A>(new A), unique_ptr<B>(new B));
允许编译器生成如下代码:
new A
new B
// 可能会抛出!
- 构造
unique_ptr<A>
- 构建
unique_ptr<B>
- 呼叫
do_work
如果 new B
抛出,那么你就泄露了 A
,因为没有构建 unique_ptr
。
将 unique_ptr
构造放入它自己的函数中消除了这个问题,因为编译器不允许并发执行函数体(因此 "new" 和“构造 unique_ptr
步骤需要一起完成)。
即给定:
do_work(make_unique<A>(), make_unique<B>())
编译器必须生成如下代码:
- 呼叫
make_unique<A>
- 呼叫
make_unique<B>
- 呼叫
do_work
或
- 呼叫
make_unique<B>
- 呼叫
make_unique<A>
- 呼叫
do_work
在没有拥有 unique_ptr
的新对象四处漂浮的地方泄漏是不可能的。
我一直在阅读 GOTW102,想知道为什么 make_unique
比其他情况更安全,或者为什么 f(new T(...))
比 [=14] 更安全=].
博客中的 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)... ) );
}
现在我想知道 f(new T(...))
是否在一般情况下是异常安全的(无泄漏),或者它是否只是在 make_unique
的情况下是异常安全的,因为增加的知识是 std::unique_ptr
不扔? (因为如果这样的话,根据我的理解,新构建的 T
无论如何都会被泄露。
原因是在函数调用或类似的调用中,参数不包含序列点(不是 "sequenced before")。例如:
do_work(unique_ptr<A>(new A), unique_ptr<B>(new B));
允许编译器生成如下代码:
new A
new B
// 可能会抛出!- 构造
unique_ptr<A>
- 构建
unique_ptr<B>
- 呼叫
do_work
如果 new B
抛出,那么你就泄露了 A
,因为没有构建 unique_ptr
。
将 unique_ptr
构造放入它自己的函数中消除了这个问题,因为编译器不允许并发执行函数体(因此 "new" 和“构造 unique_ptr
步骤需要一起完成)。
即给定:
do_work(make_unique<A>(), make_unique<B>())
编译器必须生成如下代码:
- 呼叫
make_unique<A>
- 呼叫
make_unique<B>
- 呼叫
do_work
或
- 呼叫
make_unique<B>
- 呼叫
make_unique<A>
- 呼叫
do_work
在没有拥有 unique_ptr
的新对象四处漂浮的地方泄漏是不可能的。