只是为了澄清,使用make_unique
只会在表达式中有多个分配时添加异常安全性,而不仅仅是一个,是否正确?例如异常安全和make_unique
void f(T*);
f(new T);
是完全异常安全(据分配和东西),而
void f(T*, T*);
f(new T, new T);
是不是,对不对?
只是为了澄清,使用make_unique
只会在表达式中有多个分配时添加异常安全性,而不仅仅是一个,是否正确?例如异常安全和make_unique
void f(T*);
f(new T);
是完全异常安全(据分配和东西),而
void f(T*, T*);
f(new T, new T);
是不是,对不对?
不仅当你有多个分配,但只要你可以扔在不同的地方。这样考虑:
f(make_unique<T>(), function_that_can_throw());
对战:
f(unique_ptr<T>(new T), function_that_can_throw());
在第二种情况下,编译器允许调用(按顺序):
new T
function_that_can_throw()
unique_ptr<T>(...)
显然如果function_that_can_throw
实际上抛出然后你泄漏。 make_unique
可以防止这种情况。
当然,第二个分配(就像在你的问题中)只是function_that_can_throw()
的特殊情况。
作为一般的经验法则,只需使用make_unique
,以便您的代码是一致的。当你需要一个unique_ptr
时它总是正确的(阅读:异常安全),并且它对性能没有任何影响,所以没有理由不使用它(而实际上而不是使用它引入了很多陷阱)。
我还以为你会更好的东西比较实际使用std::unique_ptr<T>
:
void f(std::unique_ptr<T>);
f(std::unique_ptr<T>(new T));
f(std::make_unique<T>());
如果引发异常无论这些调用可能泄漏。然而
void f(std::unique_ptr<T>, std::unique_ptr<T>);
g(std::unique_ptr<T>(new T), std::unique_ptr<T>(new T));
g(std::make_unique<T>(), std::make_unique<T>());
在这种情况下,使用std::unique_ptr<T>
明确的版本可以泄漏,如果一个异常被抛出(因为编译器可能会启动建设无论是临时工的前评估new
-expressions)。
作为C++ 17,异常安全问题是由[expr.call]
的参数,包括每个关联值计算和副作用的初始化一个重新措辞固定,是不定相对于该测序任何其他参数。
这里不定测序指一个之前另一个序列,但没有指定其它。
f(unique_ptr<T>(new T), function_that_can_throw());
只能有两个执行
可能为了new T
unique_ptr<T>::unique_ptr
function_that_can_throw
function_that_can_throw
new T
unique_ptr<T>::unique_ptr
这意味着它现在是异常安全。
你的问题似乎与自己相矛盾。首先你声明多分配是异常安全的,然后你展示一个例子,这在表面上与所发生的事情相反。 –
@LightnessRacesinOrbit不,我断言多个分配不是异常安全的。我说过“make_unique只在表达式中有多个分配时才会增加异常安全性”,这意味着它仅为一次分配增加了任何内容。 – Kal
啊!是的,好的,然后:) –