明確にするために、make_unique
を使用すると、1つではなく複数の割り当てがある場合に例外安全性が追加されます。例外の安全性とmake_unique
void f(T*, T*);
f(new T, new T);
は、正しくないながら?例えば
void f(T*);
f(new T);
は、完全に(限り配分やものなど)安全な例外で
明確にするために、make_unique
を使用すると、1つではなく複数の割り当てがある場合に例外安全性が追加されます。例外の安全性とmake_unique
void f(T*, T*);
f(new T, new T);
は、正しくないながら?例えば
void f(T*);
f(new T);
は、完全に(限り配分やものなど)安全な例外で
複数の割り当てがある場合だけでなく、別の場所に投げることができるときはいつでも。このことを考えてみましょう:
f(make_unique<T>(), function_that_can_throw());
バーサス:第2のケースで
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
はこの場合を防ぎます。
もちろん、2番目の割り当ては(ご質問のように)function_that_can_throw()
という特殊なケースに過ぎません。
大雑把に言えば、コードが一貫しているようにmake_unique
を使用してください。 unique_ptr
が必要な場合は常に正しい(読み取り:例外が発生しない)ので、パフォーマンスに影響はないため、使用しない理由はありません(実際にはではありません。は、 )。 C++ 17のよう
は、私が実際にstd::unique_ptr<T>
を使用して、あなたが物事を比較したほうが良いと思うだろう:
void f(std::unique_ptr<T>);
f(std::unique_ptr<T>(new T));
f(std::make_unique<T>());
スローされた例外がある場合、これらの呼び出しのどちらが漏れることができます。例外がスローされた場合(コンパイラは一時のいずれかを構築する前new
-expressionsの評価を開始する可能性があるため)。ただしこの場合
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>
を使用したバージョンは、明示的に漏れることができます。
は、例外安全性の問題が[expr.call]
すべての関連する値の計算および副作用を含むパラメータの初期化のrewordingによって固定されている、不確定それに対して配列決定します他のパラメータの
ここ
は不定は1が別の前に配列決定されるが、それはどの指定されていないことを意味し、配列決定しました。
f(unique_ptr<T>(new T), function_that_can_throw());
は
function_that_can_throw
それが今では例外安全であることを意味しnew T
unique_ptr<T>::unique_ptr
new T
unique_ptr<T>::unique_ptr
function_that_can_throw
あなたの質問は、それ自体と矛盾するようです。最初に、複数の割り当てが例外セーフであると主張します。そして、これは、これが表面的に何が起こるかの逆の例を示します。 –
@LightnessRacesinOrbitいいえ、私は、複数の割り当てが例外安全ではないと主張しました。私は "make_uniqueは式に複数の割り当てがある場合にのみ例外安全性を追加する"と言います。つまり、1つの割り当てに対して何も追加しません。 – Kal
ああ!はい、大丈夫です:) –