ときに時間がクラスのポインタ部材を有する、指示部材を管理する2つの方法がある:まず、制御値型を介して、各クラスのオブジェクトは、オブジェクト・ポインタのコピーを保持し、別のよりエレガントな方法でありますするためにスマートポインタ、オブジェクトへのポインタの共有を実現します。
スマートポインタ(スマートポインタ)一般的な手法を実装するためには使用することです参照カウント(COUNTリファレンス)。オブジェクトクラスに関連付けられた時点でのスマートポインタクラスのカウンターは、クラスには多くのオブジェクトが同じオブジェクトを指してどのように参照カウントを追跡するためのポインタを持っています。
通常ポインタスマートポインタの差スマートポインタが実際に通常のカプセル化メカニズムの層を追加するためのポインタであるが、このカプセル化メカニズムの一つの目的は、容易にオブジェクトの寿命を管理することができるスマートポインタを可能にするために提供されます。
C ++では、私たちは、あなたがオブジェクトの使用を終了した後にあなたがして、オブジェクトポインタへのポインタを作成するために、通常のポインタを使用する場合、我々は、たとえば、それを自分で削除する必要がある、ということを知っています:
ObjectType * temp_ptr =新しいのObjectType();
temp_ptr-> FOO();
temp_ptrを削除します。
多くの材料は、プログラマがtemp_ptr完成を呼び出した後temp_ptrを削除し忘れた場合、それはダングリングポインタ(ポインタをダングリング)になり、それが今のポインタを言うことであることを指摘するメモリ領域を指し、その内容はプログラマー把握することができないと制御、それかもしれませんメモリリークが発生する可能性があります。
fooは()実行時に例外をスローした場合しかし、実際には、だけではなく、このプログラムの上の段落で「忘れる」、そしてtemp_ptr尖ったオブジェクトがまだ削除しても安全ではありません。
このとき、スマートポインタの出現は、オブジェクト自体が判定された場合や条件はスマートポインタによって破壊または削除することに何の下でスマートポインタ内のオブジェクトの寿命を制御するために、実際には容易です、ユーザーが管理する必要はありません。
スマートポインタの4つのタイプがあります:株価から https://www.zhihu.com/question/20368881/answer/14918675
1)scoped_ptrを:これは、の名前のような比較的単純なスマートポインタであり、尖った物体を自動的に破壊の範囲外で得られscoped_ptrを、一例である。https://www.boost.org/ DOC / libsに/ 1_50_0 / libsに/
smart_ptr / scoped_ptr.htm 加えて、非コピー可能scoped_ptrをあなたはscoped_ptrをscoped_ptrを別の内容をコピーしようとすることができないこと、である、これは誤った複数のデストラクタを防ぐためです同じオブジェクト・ポインタポイント。
2)のshared_ptr: 多くの人が実際にこのカテゴリのshared_ptrスマートポインタであることを理解します。shared_ptrのは本質参照カウント(参照カウント)に実装され、それは、基準周波数の複製、のshared_ptrの支持複製を言うことであり、shared_ptrのは、このスマートポインタ1、及び場合回数スマートポインタが参照が0まで減少に添加されますオブジェクトが自動的に破壊されたとき。特に注目すべきなのはリングの関係を表示された場合は、件名に引用リングの数は確かにこの問題に導入されたのweak_ptrを解決するために、それは削除されません参照のshared_ptr 0の特性にすることはできないことです。
3)のweak_ptr: 多くの人々が演じるのweak_ptr役割については、独自の異なる解釈、私は理解してweak_ptrを最大の違いとのshared_ptrを持っているあなたはweak_ptrを指すように使用できるように、その参照カウントは、増加しないオブジェクトへのweak_ptrポイントでオブジェクトとのweak_ptrはまだあなたがweak_ptrをのこの時期を再訪問し、オブジェクトのデストラクタそれ、をポイントすると、実際のリターンでのweak_ptrは空のshared_ptrだろう。実際には、ときに通常の内部のshared_ptrの実装は、カウントの維持を参照していないが、二つの基準カウントを行うのshared_ptrでコピーするときにカウントされる強い参照を表し、それはweak_ptrを使用される弱参照でありますコピーの時間をカウント。自体のweak_ptr強い基準値を増加させ、そしてゼロに低減強い参照、オブジェクトは自動的に破壊されません。理由だけではなく、それまでの循環参照を説明し、問題を解決するためにweak_ptrを取りますか?循環参照の矛盾した性質が循環参照を解決するために、プログラミング言語を破るためのものではないことに注意してください、最初のループを切断しなければならない最初のステップは、それがリング上で引用されているC ++を、伝えることです最も弱い、それは破壊することができ、ループ内にある限り、本質的にループを分割することができるのweak_ptrに元のshared_ptrのように、元の循環参照問題がせることができないデストラクタそれとともに解決されました。
4)intrusive_ptr: 簡単に言えば、intrusive_ptrとのshared_ptrの違いは、それは参照カウントメカニズム自体を達成するために必要なintrusive_ptr、それはオブジェクト自体は参照カウンタが含まれている場合、あなたはintrusive_ptr使用できると言うことですオブジェクトを指していることです。実際の使用では、私はほとんどintrusive_ptr見たことがありません...
伝統的なポインタでの問題:
あなたは、ヒープ上のオブジェクトを作成すると、システムが起動に使用する場合、システムリソースを回復しませんが、あなたはそれを解放する必要があり、完全にあなたにオブジェクトの命を奪いました。
まあ、それは問題のオブジェクトの解放の責任になりたい場合は、いつ、どこでリリースを解放するために知っておく必要があります。あなたはこれらの2つの問題に対処していない場合は、メモリリークの問題やプログラムのクラッシュの原因となります。
// リソースリークはSTR1メモリが1リリースされていない呼ぶ { 文字列 * 0009 = 新しい新しい 文字列(「こんにちは」;) 文字列 * STR2 = 新しい新しい 文字列(「世界」); } // クラッシュ引き起こす2の複数の放出、 { 文字列 STR1 = * 新しい新しい 文字列(" こんにちは" ); 削除STR1を; // ... 削除 STR1を; //は、プログラムをクラッシュ }
上記の例では、解放ポインタは同じスコープ内で行われ、それらは容易にプログラミング上記のコードで問題を回避することができます。
しかし、大規模なプロジェクトのために、オブジェクトは、1つの場所に作成され、対応するスコープにリリースされていないかもしれないが、多くの場合、このような問題のために、オブジェクトを破壊するために行くなど、特定のイベント、例外処理の場合まで待ちます調査から出てくることは困難です。
したがって、責任自爆ポインタのためのメカニズムを引用する必要があります。むしろ、プログラマよりも、手動で自分自身を破壊します。スマートポインタは、正確なメカニズムです。
:スマートポインタの原則をカウントリファレンス(から:ほとんど知られている:小豆6月を敷設乾燥)
1.ヒープからリソースを申請する場合は、ヒープがカウントのためのリソースを適用しながら、後にすべてのオブジェクトがリソース共有を指しているように、我々は、このリソースを指すように、スマートポインタオブジェクトを作成しますリソースのカウントは、参照の数は一つだけを頼りにするように。
参照カウントを共有オブジェクトPTR1のPTR2に割り当てられたオブジェクトが2になる2。
3. PTR2オブジェクトを削除し、その参照カウントは、対応する1に低減されます。
4.削除PTR1オブジェクトの参照カウントがゼロで、リソースの解放に行きます。
ほとんど知られている:ドライRooの6月を敷設次のコードから
#pragma一旦 テンプレート < クラス T> クラスSharedPointer { パブリック: // デフォルトコンストラクタ、内部ポインタは、任意のリソース参照カウントを指していない、それが任意のリソースにバインドされていないため、0である SharedPointer():m_refCount(nullptr) 、m_pointer (nullptr A){} // コンストラクタ、既に割り当てられたリソースを指すように初期化 SharedPointer(T * adoptTarget):m_refCount(nullptr A)、m_pointer(adoptTarget) { AddReference(); } // コンストラクタ他のオブジェクト新しいオブジェクトの作成 SharedPointer(CONST SharedPointer <T>&コピー) :m_refCount(copy.m_refCount)、m_pointer(copy.m_pointer) { AddReference()。 } //時間が0のときデストラクタ、基準カウントダウン、リソースが解放され 、仮想〜SharedPointer() { RemoveReference(); } // 割り当て // 左は、それがもはや点の意味を示さない、値が割り当てられますリソース、参照カウントがデクリメントされるように、 // それが新しいリソース、いずれかによって、このカウントに対応する参照リソースを指していること後 SharedPointer <T>&演算子 =(CONST SharedPointer <T>& ) { IF(この!=&その) { RemoveReference(); この - > m_pointer = that.m_pointer; この - > m_refCount = that.m_refCount。 AddReference(); } m_pointerと、戻り* これは; } //は、同じリソースを指すか否かを判断 BOOLの 演算子 ==(CONST SharedPointer <T>&OTHER) { 戻り m_pointer == ; other.m_pointer } BOOLの 演算子 =(!のConst SharedPointer <T>&OTHER) { リターン!演算子 == (その他); } // デリファレンス T&演算子 *()constの { リターン * } //は、オブジェクトのパブリックメンバー知ら呼び出す のT *の演算子を- >()のconst { 戻りm_pointer; } // 参照カウント数の取得 int型 GetReferenceCount()constとして { IF (m_refCountが) { 返す * m_refCountを; } 他 { リターン - 1。; } } 保護: // nullpterで、リソースの参照カウントを作成し、1に初期化される // そうでない場合は、参照カウントがインクリメントされます。 空AddReference() { IF (m_refCount) { ( * m_refCount)++ ; } 他 { m_refCount = 新新 INT(0 ); * = m_refCount 1。; } } // すべてのリソースを解放する際に一つの参照カウントが0になると 、ボイドRemoveReference() { IFを(m_refCount) { ( * m_refCount) - ; IF(* m_refCount == 0 ) { 削除m_refCountと、 削除m_pointerと、 m_refCount = 0。 m_pointer = 0 ; } } } プライベート: int型 * m_refCount。 Tの *のm_pointer。 }。
参考:
https://baike.baidu.com/item/%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/10784135?fr=aladdin