web-dev-qa-db-ja.com

C ++ 17でのstd :: make_shared()の変更

cppref では、C++ 17まで次のことが成り立ちます。

f(std::shared_ptr<int>(new int(42)), g())などのコードは、new int(42)の後にgが呼び出されて例外をスローした場合にメモリリークを引き起こす可能性がありますが、f(std::make_shared<int>(42), g())は安全です。

C++ 17で導入された変更により、これが適用されなくなるのは疑問です。

27
Lingxi

関数の引数の評価順序は P0400R によって変更されます。

変更前は、関数の引数の評価は相互に関連付けられていません。これは、g()の評価がstd::shared_ptr<int>(new int(42))の評価に挿入される可能性があることを意味し、引用されたコンテキストで説明されている状況を引き起こします。

変更後、関数引数の評価はインターリーブなしで不定にシーケンスされます。つまり、std::shared_ptr<int>(new int(42))のすべての副作用はg()の副作用の前または後に発生します。 g()がスローする場合を考えてみましょう。

  • std::shared_ptr<int>(new int(42))のすべての副作用がg()の副作用の前に発生する場合、割り当てられたメモリは_std::shared_ptr<int>_のデストラクタによって割り当て解除されます。

  • std::shared_ptr<int>(new int(42))のすべての副作用がg()の副作用の後に発生する場合、メモリ割り当てさえありません。

いずれにせよ、とにかく再びメモリリークはありません。

17
xskxzr

P0145R ペーパー( 受け入れられた C++ 17へ)は、以下を含むいくつかのC++構文の評価順序を改良します。

後置式は左から右に評価されます。これには、関数呼び出しとメンバー選択式が含まれます

具体的には、このペーパーでは、標準の5.2.2/4段落に次のテキストを追加しています。

Postfix-expressionは、expression-listの各式とデフォルト引数の前にシーケンスされます。パラメーターの初期化に関連するすべての値計算と副作用、および初期化自体は、後続のパラメーターの初期化に関連するすべての値計算と副作用の前にシーケンスされます。

20
lisyarus