2016-09-23 23 views
3

std::vector<>::emplace_back()に例外がスローされたらどうなりますか?例えばstd :: vector <> :: emplace_back()の例外は安全ですか?

class Foo { 
public: 
    Foo(int bar) { 
    if (bar == 4) throw std::exception("Something went wrong"); 
    } 
} 

std::vector<std::unique_ptr<Foo>> foo_list; 
foo_list.emplace_back(new Foo(3)); 
try { 
    foo_list.emplace_back(new Foo(4)); 
} catch (std::exception error) { 
    // How bad is it? 
} 
// Whats inside foo_list now? 

私はベクトルがちょうど最初のFooオブジェクトが含まれていることを期待します。

この場合ですか?これは標準によって保証されていますか?

また、メモリリークがありますか?

+1

例外がスローされたときにemplace_backが実行されていません... –

+0

http://en.cppreference.com/w/cpp/container/vector/emplace_back自分自身を参照してください – Hayt

+3

関数を呼び出す前に関数の引数を評価する必要があります。コンストラクタが最初にスローされます。 emplace_backは決して呼び出されませんでした。 –

答えて

8

私はベクトルが最初のFooオブジェクトを含むと予想します。

この場合ですか?これは標準によって保証されていますか?

はい。上記のコメントでは、emplace_backは、Fooコンストラクタがその関数の引数を初期化している間にスローするため、決して呼び出されないことが既に説明されています。

しかし...

も:任意のメモリリークがあるだろうか?

はい、あなたは(もOverload Journal #134 - August 2016に発表された)、私はInserting into a container of smart pointers with emplace_back(new X)で説明したアンチパターンを使用しています。 emplace_backは、ベクターを再割り当てする必要があり、それが原因メモリ不足に失敗したときに

問題が起こります。関数に渡されたポインタが失われるので、Fooオブジェクトがリークします。これは、(Fooコンストラクタがスローされません)最初の挿入のために発生します代わりに、

foo_list.emplace_back(new Foo(3)); 

unique_ptrの容器に生のポインタを挿入するためにemplace_backを使用しないでください使用make_unique

foo_list.emplace_back(std::make_unique<Foo>(3)); 

かC++ 11を使用する必要がある場合は、unique_ptrを構築し、未処理のポインタではなく挿入または置き換えます。

foo_list.emplace_back(std::unique_ptr<Foo>(new Foo(3))); 

この方法では、オブジェクトはunique_ptrによってすぐに所有されます。したがって、emplace_backの内部で例外が発生した場合、オブジェクトは正しく破棄されます。

+0

ありがとうございました。私はまた、例えばstd :: tieについて知らなかった。非常に便利 :) –

関連する問題