ホームページ >バックエンド開発 >C++ >`make_shared` とコンストラクターで初期化された `shared_ptr`: パフォーマンスと例外の安全性の違いは何ですか?

`make_shared` とコンストラクターで初期化された `shared_ptr`: パフォーマンスと例外の安全性の違いは何ですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-11 00:40:16481ブラウズ

`make_shared` vs. Constructor-Initialized `shared_ptr`: What's the Performance and Exception Safety Difference?

make_shared とコンストラクターで初期化されたshared_ptr の違い

シナリオ

次のコード スニペットを考えてみましょう。

std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
std::shared_ptr<Object> p2(new Object("foo"));

理由を理解するmake_shared は、shared_ptr コンストラクターを直接使用するより効率的です。関連する操作の段階的な分析。

操作の比較

make_shared

  • 単一のヒープ割り当てを実行して、両方のコントロールに連続したメモリ ブロックを作成します。ブロック(メタデータ)と管理対象object.

Constructor-Initializedshared_ptr

  • new Obj("foo") を呼び出し、管理対象オブジェクトのヒープ割り当てを作成します。
  • Then 、shared_ptr コンストラクターが呼び出され、コントロールに対して別のヒープ割り当てが実行されます。 block.

メモリ割り当て

make_shared はメモリを 1 回だけ割り当てますが、コンストラクタで初期化されたshared_ptr はメモリを 2 回割り当てます。これにより、make_shared がより効率的になります。

例外の安全性

C 17 では、関数の引数の評価順序が改訂され、コンストラクターで初期化されるshared_ptr アプローチによる例外の安全性の問題が排除されました。ただし、次の例を考えてみましょう。

void F(const std::shared_ptr<Lhs> &lhs, const std::shared_ptr<Rhs> &rhs) { /* ... */ }

F(std::shared_ptr<Lhs>(new Lhs("foo")), std::shared_ptr<Rhs>(new Rhs("bar")));

Rhs コンストラクター中に例外がスローされた場合、Lhs に割り当てられたメモリは、shared_ptr コンストラクターにすぐに渡されなかったため、失われます。 make_shared は、この中間ステップを排除することでこの問題を回避します。

make_shared の欠点

ただし、make_shared には欠点があります。制御ブロックと管理オブジェクトを単一のヒープ ブロックに割り当てるため、両方を独立して割り当て解除することはできません。これは、弱いポインタが制御ブロックを無期限に存続させ、制御ブロックと管理対象オブジェクトの両方の割り当てが解除されなくなる可能性があることを意味します。

以上が`make_shared` とコンストラクターで初期化された `shared_ptr`: パフォーマンスと例外の安全性の違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。