只是爲了澄清,使用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
啊!是的,好的,然後:) –