2013-10-20 17 views
11

明確にするために、make_uniqueを使用すると、1つではなく複数の割り当てがある場合に例外安全性が追加されます。例外の安全性とmake_unique

void f(T*, T*); 

f(new T, new T); 

は、正しくないながら?例えば

void f(T*); 

f(new T); 

は、完全に(限り配分やものなど)安全な例外で

+0

あなたの質問は、それ自体と矛盾するようです。最初に、複数の割り当てが例外セーフであると主張します。そして、これは、これが表面的に何が起こるかの逆の例を示します。 –

+0

@LightnessRacesinOrbitいいえ、私は、複数の割り当てが例外安全ではないと主張しました。私は "make_uniqueは式に複数の割り当てがある場合にのみ例外安全性を追加する"と言います。つまり、1つの割り当てに対して何も追加しません。 – Kal

+0

ああ!はい、大丈夫です:) –

答えて

21

複数の割り当てがある場合だけでなく、別の場所に投げることができるときはいつでも。このことを考えてみましょう:

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のよう

+2

ありがとう、これは私が探していたものです。あなたの2^13人の担当者を破棄して申し訳ありません。 – Kal

+1

@KalそれはOKです、私は現在2^14を目指しています...;) – syam

6

は、私が実際に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>を使用したバージョンは、明示的に漏れることができます。

2

は、例外安全性の問題が[expr.call]

すべての関連する値の計算および副作用を含むパラメータの初期化のrewordingによって固定されている、不確定それに対して配列決定します他のパラメータの

ここ

は不定は1が別の前に配列決定されるが、それはどの指定されていないことを意味し、配列決定しました。

f(unique_ptr<T>(new T), function_that_can_throw()); 

  • function_that_can_throwそれが今では例外安全であることを意味しnew Tunique_ptr<T>::unique_ptr
  • new Tunique_ptr<T>::unique_ptrfunction_that_can_throw
      実行

      の2つだけの可能な順序を持つことができます。

  • 関連する問題