从这个thread,我们知道以下代码是异常安全的(假设T( U(std::move(v)) )
是异常安全的,例如,不抛出,这是库用户的责任)
auto p = new T( U(std::move(v)) );
这里的关键点是在内存分配后评估初始化表达式U(std::move(v))
。现在考虑std::make_unique()
对应方。
auto p = std::make_unique<T>( U(std::move(v)) );
即使在调用U(std::move(v))
之前,也会评估初始化表达式std::make_unique()
。如果此后内存分配失败,v
将被移动/修改,不会提供强大的异常安全性。但是,如果我们写
std::unique_ptr<T> p(new T( U(std::move(v)) ));
新表达机制启动,我们重新获得强大的异常安全性。看起来像一个例外安全的make_unique
必须是一个宏。
#define MAKE_UNIQUE(T, ...) ::std::unique_ptr<T>(new T(__VA_ARGS__))
我对异常安全感到陌生,并想知道我的推理是否正确。如果是这样,如果有比上面的宏更好的解决方案吗?