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で導入された変更により、これが適用されなくなるのは疑問です。
関数の引数の評価順序は 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()
の副作用の後に発生する場合、メモリ割り当てさえありません。
いずれにせよ、とにかく再びメモリリークはありません。