5

で例外がスローされるとどうなり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 オブジェクトだけが含まれていると思います。

これは事実ですか?そして、これは標準によって保証されていますか?

また、メモリリークが発生する可能性はありますか?

4

1 に答える 1

10

ベクトルには最初の Foo オブジェクトだけが含まれていると思います。

これは事実ですか?そして、これは標準によって保証されていますか?

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

しかし ...

また、メモリリークが発生する可能性はありますか?

はい、 emplace_back(new X) を使用してスマート ポインターのコンテナーへの挿入で説明したアンチパターンを使用しています(オーバーロード ジャーナル #134 - 2016 年 8 月にも公開されています)。

この問題はemplace_back、ベクトルを再割り当てする必要があり、メモリ不足のために失敗したときに発生します。関数に渡されたポインターが失われるため、Fooオブジェクトがリークします。これは、最初の挿入 (Fooコンストラクターがスローしない場所) で発生する可能性があります。

foo_list.emplace_back(new Foo(3));

emplace_backのコンテナに未加工のポインタを挿入するために使用しないでくださいunique_ptr。代わりに次を使用して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、オブジェクト内で例外が発生した場合、オブジェクトは正しく破棄されます。

于 2016-09-23T14:00:06.810 に答える