web-dev-qa-db-ja.com

make_sharedを使用してshared_ptrを作成することの欠点はありますか

make_shared<T>()を使用する代わりにshared_ptr<T>(new T)を使用することの欠点はありますか。

ブーストドキュメント 状態

特定のタイプのオブジェクトを作成し、それにshared_ptrを返すファクトリ関数に対するユーザーからの要求が繰り返されています。利便性とスタイルに加えて、このような関数は、オブジェクトとそれに対応する制御ブロックの両方に単一の割り当てを使用でき、shared_ptrの構築オーバーヘッドのかなりの部分を排除できるため、例外安全性とかなり高速です。これにより、shared_ptrに関する主要な効率性の不満の1つが解消されます。

51
Tobias Furuholm

私は少なくとも2つ知っています。

  • 割り当てを管理する必要があります。それほど大きなものではありませんが、一部の古いAPIは、削除する必要のあるポインターを返すのが好きです。
  • カスタム削除機能はありません。これがサポートされていない理由はわかりませんが、サポートされていません。つまり、共有ポインタはバニラデリッターを使用する必要があります。

かなりの弱点。したがって、常にmake_sharedを使用するようにしてください。

26
deft_code

@deft_codeによって提示されたポイントに加えて、さらに弱いもの:

  • 特定のオブジェクトに対するすべてのweak_ptrsが終了した後に存続するshared_ptrsを使用する場合、このオブジェクトのメモリは、最後のweak_ptrが終了するまで制御ブロックとともにメモリに存続します。つまり、オブジェクトは破棄されますが、最後のweak_ptrが破棄されるまで割り当てが解除されません。
39
sbk

から http://www.codesynthesis.com/~boris/blog/2010/05/24/smart-pointers-in-boost-tr1-cxx-x0/

make_shared()実装のもう1つの欠点は、オブジェクトコードサイズが大きくなることです。この最適化の実装方法により、make_shared()で使用するオブジェクトタイプごとに、追加の仮想テーブルと一連の仮想関数がインスタンス化されます。

14
Viktor Sehr

さらに、make_sharedはファクトリパターンと互換性がありません。これは、ファクトリ関数内でmake_sharedを呼び出すと、ライブラリコードが呼び出され、ライブラリコードがアクセスできないnewを呼び出すためですクラスを呼び出すことができないため)プライベートコンストラクター(ファクトリパターンに正しく従う場合、コンストラクターはプライベートである必要があります)。

8
Rok Strniša

make sharedを使用すると、保持されているオブジェクトの割り当ておよび割り当て解除を指定できません。完了しました。

それが必要な場合は、代わりにstd::allocate_shared<T>を使用してください。

std::vector<std::shared_ptr<std::string>> avec; 
std::allocator<std::string> aAllocator;
avec.Push_back(std::allocate_shared<std::string>(aAllocator,"hi there!"));

ベクトルにアロケータについて通知する必要がないことに注意してください。

カスタムアロケーターを作成するには、こちらをご覧ください https://stackoverflow.com/a/542339/1149664

7
Johan Lundberg