違いは何ですか:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
そして
std::shared_ptr<int> p = std::make_shared< int >();
?
どちらを好むのか、なぜですか?
P. S.これはすでに回答されているはずですが、同様の質問は見つかりません。
どちらの例も、必要以上に冗長です。
std::shared_ptr<int> p(new int); // or '=shared_ptr<int>(new int)' if you insist
auto p = std::make_shared<int>(); // or 'std::shared_ptr<int> p' if you insist
違いは何ですか?
主な違いは、1つ目は2つのメモリ割り当てを必要とすることです。1つは管理対象オブジェクト(new int
)用、もう1つは参照カウント用です。 make_shared
は、単一のメモリブロックを割り当て、その中に両方を作成する必要があります。
どちらを好むのか、なぜですか?
通常、make_shared
を使用する方が効率的です。別の回答に記載されているように、管理対象オブジェクトへの生のポインタが存在しないため、メモリリークの可能性も回避されます。
ただし、コメントに記載されているように、共有カウントの削除を妨げる弱いポインターが残っている場合、オブジェクトが破棄されてもメモリが解放されないという潜在的な欠点があります。
対照的に、宣言std::shared_ptr<T> p(new T(Args...))
は少なくとも2つのメモリ割り当てを実行するため、不要なオーバーヘッドが発生する可能性があります。
また、f(shared_ptr<int>(new int(42)), g())
は、gが例外をスローした場合にメモリリークを引き起こす可能性があります。 make_sharedが使用されている場合、この問題は存在しません。
だから、make_shared
可能であればアプローチします。
make_shared
はデフォルトの割り当て/割り当て解除機能の使用に制限されているため、さらに制御したい場合、make_shared
はオプションではありません。言い換えれば、
std::shared_ptr<uint8_t>(p, [](uint8_t *p){ /*user code */});
make_shared
を使用することはできません。代わりにallocate_shared
を使用することもできますが、指定できるのはアロケーターのみで、削除機能は指定できません。ラップされたクラスの割り当てと削除を制御する必要がある場合があります。