假设我有一个函数reset
:
template<typename T, typename... Args>
void reset(unique_ptr<T>& p, Args&&... args)
{
// implementation (1)
p.reset(new T(forward<Args>(args)...));
// implementation (2)
p = make_unique<T>(forward<Args>(args)...);
}
我是否正确:
对于实现(1),如果在销毁
p
的原pointee时抛出异常,将泄漏new
内存;实现(2),什么都不能泄露;
所以我们应该更喜欢 (2) 而不是 (1)。
最佳答案
作为 Jonathan Wakely points out ,这一点没有实际意义,因为如果析构函数无论如何都会抛出,则 unique_ptr::reset
的行为是未定义的。
如果析构函数抛出,两个版本都有 UB,所以这不是偏爱其中一个的理由。
[unique.ptr.single.modifiers] (标准草案)
3 Requires: The expression
get_deleter()(get())
shall be well formed, shall have well-defined behavior, and shall not throw exceptions.
即使行为定义明确...
(1) 不会泄漏。 unique_ptr
在销毁旧参数之前取得参数的所有权。
4 Effects: Assigns
p
to the stored pointer, and then if the old value of the stored pointer,old_p
, was not equal tonullptr
, callsget_deleter()(old_p)
. [ Note: The order of these operations is significant because the call toget_deleter()
may destroy*this
. — end note ]
偏爱其中一个的原因
- (1) 仅需要 C++11,(2) 需要 C++14 或您自己的
make_unique
样板。 - (2) 没有对
new
的显式调用,因此使用旧的经验法则更容易推断内存整洁度:“每个 new 一个 delete”。
关于c++ - std::unique_ptr<T>::reset 的强异常保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38447426/