[解決済み] C++のスマートポインタの実装にはどのようなものがありますか?
質問
比較、長所、短所、使用するタイミングは?
これは ガベージコレクションスレッド のスピンオフで、私が単純な答えだと思ったものが、いくつかの特定のスマート ポインターの実装に関する多くのコメントを生成したため、新しい投稿を始める価値があると思われます。
最終的には、C++ におけるスマート ポインターのさまざまな実装は何であり、それらをどのように比較するのか、という質問です。 単純な長所と短所、または、そうでなければ動作するはずだと思うかもしれない何かに対する例外とゴッチャだけです。
私が使ったことのある、あるいは少なくともざっと見て、答えとして使うことを考えたいくつかの実装と、それらの違いや類似点についての私の理解を以下に掲載しました。
目標は、いくつかの新しいオブジェクトやライブラリについて学ぶこと、またはすでに広く使用されている既存の実装について私の使用法と理解を修正し、他の人のための適切なリファレンスに仕上げることです。
どのように解決するのですか?
C++03
std::auto_ptr
- おそらくオリジナルのひとつで、限られたガベージコレクション機能しか提供しない初稿症候群に悩まされていました。最初の欠点は
delete
を呼び出すので、配列に割り当てられたオブジェクトを保持するためには受け入れがたいことです (
new[]
). これはポインタの所有権を取るので、2つの自動ポインタが同じオブジェクトを含むことはできません。アサインメントによって所有権が移され
rvalue
をヌルポインタにリセットします。これはおそらく最悪の欠点につながります。前述のようにコピーできないため、STL コンテナ内では使用できません。どのような使用例に対しても最終的な打撃は、C++ の次の標準では非推奨となる予定であることです。
std::auto_ptr_ref
- これはスマートポインタではありません。
std::auto_ptr
と併用され、特定の状況下でのコピーや割り当てを可能にするためのものです。具体的には、コンストラクタでない
std::auto_ptr
を
lvalue
として知られている Colvin-Gibbons のトリックを使用しています。
移動コンストラクタ
を使用して所有権を移譲します。
逆に、おそらく
std::auto_ptr
は、自動ガベージ コレクションのための汎用スマート ポインターとして使用されることを意図していなかったのでしょう。私の限られた理解や推測の大部分は
Herb Sutter の auto_ptr の効果的な使用法
に基づいており、常に最も最適化された方法ではないものの、私は定期的にそれを使用しています。
C++11
std::unique_ptr
- こちらは入れ替わりで登場する
std::auto_ptr
の弱点を修正するための重要な改善点を除けば、非常によく似たものになるでしょう。
std::auto_ptr
の弱点を修正するための重要な改良が施されています。
lvalue
の保護、STL コンテナやアルゴリズムでの使用などです。パフォーマンス オーバーヘッドとメモリ フットプリントが制限されているため、これは生のポインタを置き換える、あるいは所有すると表現するのがより適切な理想的な候補と言えます。unique" が意味するように、ポインタの所有者は一人であり、以前の
std::auto_ptr
.
std::shared_ptr
- これはTR1がベースになっていると思いますが
boost::shared_ptr
をベースにしていますが、エイリアスやポインタ演算を含むように改良されています。要するに、参照カウントされたスマートポインタを、動的に割り当てられたオブジェクトに巻き付けるのです。shared" が意味するように、ポインタは複数の共有ポインタによって所有することができ、最後の共有ポインタの最後の参照がスコープ外になったとき、そのオブジェクトは適切に削除されるでしょう。これらはスレッドセーフでもあり、ほとんどの場合、不完全な型も扱うことができます。
std::make_shared
を効率的に構築するために使用することができます。
std::shared_ptr
を効率的に構築することができます。
std::weak_ptr
- 同様にTR1をベースとし
boost::weak_ptr
. が所有するオブジェクトへの参照です。
std::shared_ptr
が存在する場合、そのオブジェクトの削除を防ぐことはできません。
std::shared_ptr
の参照カウントはゼロになります。生のポインタにアクセスするためには、まず最初に
std::shared_ptr
を呼び出すことで
lock
を呼び出すと、空の
std::shared_ptr
を返します。これは主に、複数のスマートポインタを使用する際に、不定のぶら下がり参照カウントを避けるために便利です。
ブースト
boost::shared_ptr
- おそらく最も多様なシナリオ(STL、PIMPL、RAIIなど)で使用するのが最も簡単です。これは共有参照されたスマートポインタです。いくつかの状況でパフォーマンスやオーバーヘッドに関する不満を聞いたことがありますが、その議論が何だったのか思い出せないので無視したに違いありません。どうやら、保留中の標準 C++ オブジェクトになるほど人気があったようで、スマート ポインターに関する規範を超える欠点は思い浮かびません。
boost::weak_ptr
- 前述した
std::weak_ptr
への非所有者の参照が可能になります。
boost::shared_ptr
. 驚くなかれ、あなたは
lock()
を呼び出して共有ポインタにアクセスし、それがすでに破棄されている可能性があるため、それが有効であることを確認する必要があります。返された共有ポインタを保存せず、それを使用し終わったらすぐにスコープの外に出すようにします。そうしないと、参照カウントがハングアップしてオブジェクトが破棄されないという循環参照問題にすぐに戻ってしまいます。
boost::scoped_ptr
- これはシンプルなスマートポインタ・クラスで、オーバーヘッドはほとんどありません。
boost::shared_ptr
に代わるものとして設計されたものです。これは
std::auto_ptr
と同等ですが、STLコンテナの要素として、あるいは同じオブジェクトへの複数のポインタとして安全に使用することができないという点で特に注意が必要です。
boost::intrusive_ptr
- 私はこれを使ったことがありませんが、私の理解では、これは独自のスマートポインタ互換のクラスを作成するときに使用するように設計されています。参照カウントを自分で実装する必要があり、クラスを汎用的にしたい場合はいくつかのメソッドを実装する必要があり、さらに独自のスレッドセーフを実装する必要があります。さらに、独自のスレッドセーフを実装する必要があります。プラス面では、これはおそらく、あなたが望むスマートさの程度を正確に選択する最もカスタムな方法を提供します。
intrusive_ptr
は一般的に
shared_ptr
よりも効率的です。なぜなら、オブジェクトごとに単一のヒープ割り当てができるからです。
(Arvidに感謝)
boost::shared_array
- これは
boost::shared_ptr
を配列のために使用します。基本的には
new []
,
operator[]
そしてもちろん
delete []
はベイクインされます。これはSTLコンテナで使用することができ、私の知る限りでは、すべての
boost:shared_ptr
を使うことはできませんが
boost::weak_ptr
を使うことはできません。しかし、代わりに
boost::shared_ptr<std::vector<>>
を使うことで、同様の機能を持たせることができます。
boost::weak_ptr
を使うことができるようになりました。
boost::scoped_array
- これは
boost::scoped_ptr
を配列のために使用します。と同様に
boost::shared_array
と同様、配列に必要な機能はすべて組み込まれています。これはコピーできないので、STLコンテナでは使えません。私は、これを使いたいと思ったときは、おそらくどこでも
std::vector
. どちらが実際に速いか、オーバーヘッドが少ないかを判断したことはありませんが、このスコープ付き配列はSTL vectorよりもはるかに少ないようです。スタック上にアロケーションを維持したい場合は
boost::array
を考えてみてください。
Qt
QPointer
- Qt 4.0 で導入されたこのスマートポインタは、quot;weak" でしか動作しません。
QObject
と派生クラスでのみ動作し、Qt フレームワークでは
ほとんど
であり、それは実際に制限ではありません。しかし、制限があります。すなわち、それは "strong" ポインタを提供しないことと、基礎となるオブジェクトが有効であるかどうかでチェックできるものの
isNull()
でチェックできますが、特にマルチスレッド環境では、そのチェックをパスした直後にオブジェクトが破壊されてしまう可能性があります。Qtの人たちはこれを非推奨と考えているようです。
QSharedDataPointer
- これは、次のようなスマート・ポインタです。
boost::intrusive_ptr
に匹敵するものです。スレッドセーフですが、参照カウントメソッド (
ref
と
deref
) をサブクラス化することで実現できます。
QSharedData
. Qtの多くと同様に、オブジェクトは十分な継承によって使用するのが最善であり、すべてをサブクラス化することが意図された設計であるように思われます。
QExplicitlySharedDataPointer
- と非常によく似ています。
QSharedDataPointer
を暗黙のうちに呼び出さないことを除けば、非常によく似ています。
detach()
. 私はこれをバージョン 2.0 の
QSharedDataPointer
参照カウントがゼロになった後に切り離すタイミングを正確に制御するためのわずかな増加は、まったく新しいオブジェクトの価値が特にないため、これをバージョン 2.0 と呼ぶことにします。
QSharedPointer
- アトミック参照カウント、スレッドセーフ、共有可能なポインタ、カスタム削除(配列サポート)、スマートポインタがあるべき姿のように思えます。これは私が Qt で主にスマートポインタとして使用しているもので、次のものと同等だと思います。
boost:shared_ptr
と同等ですが、おそらく Qt の多くのオブジェクトのようにかなり多くのオーバーヘッドがあります。
QWeakPointer
- 繰り返されるパターンを感じますか?ちょうど
std::weak_ptr
と
boost::weak_ptr
と組み合わせて使用されます。
QSharedPointer
と併用します。そうしないとオブジェクトが削除されないような スマートポインタ間の参照が必要な場合です。
QScopedPointer
- この名前も見覚えがあるはずで、実はこの名前は
boost::scoped_ptr
Qtバージョンの共有ポインタや弱ポインタとは異なります。のオーバーヘッドなしで単一オーナーのスマートポインタを提供するために機能します。
QSharedPointer
のようなオーバーヘッドがなく、互換性、例外セーフコード、および
std::auto_ptr
または
boost::scoped_ptr
のためのものです。
関連
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] スマートポインターとは何ですか?