私が理解している限りでは、C++ 14はstd::make_unique
を導入しました。なぜなら、パラメータ評価の順序が指定されていないため、これは安全ではなかったからです。
f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A
(説明:評価が最初に生のポインター用のメモリーを割り振ってからg()
を呼び出し、std::unique_ptr
構造の前に例外がスローされると、メモリーはリークされます。)
std::make_unique
を呼び出すことは呼び出しの順番を制限するための方法であり、したがって物事を安全にします。
f(std::make_unique<MyClass>(param), g()); // Syntax B
それ以来、C++ 17は評価順序を明確にし、構文Aも安全なものにしました。それでは、私の質問です。C++ 17でstd::make_unique
のコンストラクターよりstd::unique_ptr
を使用する理由はまだありますか。いくつか例を挙げていただけますか?
今のところ、私が想像できる唯一の理由はMyClass
を一度だけタイプすることができるということです(std::unique_ptr<Base>(new Derived(param))
の多態性に頼る必要がないと仮定して)。ただし、特にstd::make_unique
のコンストラクターでは許可されているのに対し、std::unique_ptr
では削除文字の指定が許可されていない場合は、これはかなり弱い理由のように思われます。
念のために言っておきますが、私は標準ライブラリからstd::make_unique
を削除することを支持してはいません(少なくとも下位互換性のためには意味があります)が、それでもstd::unique_ptr
を優先する状況がまだあるのではないかと思います。
あなたはその主な理由が取り除かれたのは正しいです。まだ 新しい使用しない というガイドラインがあり、それはタイピングの理由が少ないということです(タイプを繰り返す必要も、ワードnew
を使用する必要もありません)。確かにこれらは強力な議論ではありませんが、私は私のコードでnew
を見ないことが本当に好きです。
また、一貫性を忘れないでください。あなたは絶対にmake_shared
を使うべきなので、make_unique
を使うことは自然でパターンに合っています。構文Aがもっと多くの書き換えを必要とする場合は、std::make_unique<MyClass>(param)
をstd::make_shared<MyClass>(param)
(またはその逆)に変更するのは簡単です。
make_unique
はT
をT[]
およびT[N]
と区別しますが、unique_ptr(new ...)
は区別しません。
new[]
されたポインタをunique_ptr<T>
に渡すか、またはnew
されたポインタをunique_ptr<T[]>
に渡すことで、未定義の動作を簡単に得ることができます。
その理由は、重複することなくコードを短くすることです。比較する
f(std::unique_ptr<MyClass>(new MyClass(param)), g());
f(std::make_unique<MyClass>(param), g());
MyClass
、new
、中括弧を保存します。 ptr と比較すると、 make の方が1文字だけ多くなります。
new
を使用するたびに、生涯の正確性について特別に注意深く監査する必要があります。それは削除されますか? 1回だけ?
make_unique
を使用するたびにこれらの追加の特性が得られるわけではありません。所有オブジェクトが「正しい」存続期間を持つ限り、それは再帰的にユニークポインタを「正しい」にします。
さて、unique_ptr<Foo>(new Foo())
はすべての点で同一です1 make_unique<Foo>()
へ。監査するためにnew
を使用するには、より単純な「ソースコードをgrepする」だけが必要です。
1 実際には嘘です。完璧な転送は完璧ではありません、{}
、デフォルトのinit、配列はすべて例外です。
それ以来、C++ 17は評価順序を明確にし、構文Aも安全にしました。
それは本当に十分ではありません。安全性の保証として最近導入された技術条項に依存することは、非常に堅牢なプラクティスではありません。
new
を他の場所で使用することを奨励します。例をコピーして貼り付けます。new
を他の場所に移動する可能性があります(OK、認められました、その可能性はあまりありません)。一般的に、コードが適切/堅牢/明確に有効であることは良い考えですwithout標準。
(これは基本的に私が行ったのと同じ引数です ここ タプル破壊の順序について。)