c++ - 引数 - スマートポインタ 生ポインタ




スマートポインタとは何ですか?いつスマートポインタを使用しますか? (10)

スマートポインタとは何ですか?いつスマートポインタを使用しますか?


Chris、Sergdev、Llyodの定義は正しい。 私はもっ​​と簡単な定義を好みますが、私の人生を単純に保つだけです。スマートポインタは単に->*演算子をオーバーロードするクラスです。 つまり、あなたのオブジェクトは意味的にはポインタのように見えますが、参照カウント、自動破壊などを含め、よりクールなものにすることができます。ほとんどの場合、 shared_ptrauto_ptrで十分ですが、小さな独自性のセットに従います。


TをこのチュートリアルのクラスとするPointers in C ++は3つのタイプに分けることができます:

1) 生ポインタ

T a;  
T * _ptr = &a; 

それらはメモリ内のある場所にメモリアドレスを保持します。 プログラムが複雑になりにくいため、慎重に使用してください。

constデータまたはアドレスを持つポインタ{逆方向に読み込む}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

constのデータ型Tへのポインタ。 つまり、ポインタを使用してデータ型を変更することはできません。 すなわち*ptr1 = 19 ; 動作しないでしょう。 しかし、あなたはポインタを動かすことができます。 すなわち、 ptr1++ , ptr1-- ; 等が動作します。 後方に読む:const型のT型へのポインタ

  T * const ptr2 ;

データ型Tへのconstポインタ。 ポインタを移動することはできませんが、ポインタが指す値を変更することができます。 すなわち、 *ptr2 = 19は動作しますが、 ptr2++ ; ptr2--は動作しptr2++ ; ptr2-- ptr2++ ; ptr2--などは動作しません。 後方に読む:const型Tへのポインタ

const T * const ptr3 ; 

constデータ型Tへのconstポインタ。 つまり、ポインタを移動することも、データ型ポインタをポインタにすることもできません。 すなわち、 ptr3-- ; ptr3++ ; *ptr3 = 19; 動作しないでしょう

3) スマートポインタ :{ #include <memory> }

共有ポインタ

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

参照カウントを使用して実装され、ポインタによって指し示されるオブジェクトを指している「物」の数を追跡します。 このカウントが0になると、オブジェクトは自動的に削除されます。つまり、オブジェクトを指すshare_ptrがすべてスコープから外れると、オブジェクト化されたオブジェクトが削除されます。 これは、あなたがnewを使って割り当てたオブジェクトを削除しなければならないという頭痛を取り除きます。

Weak Pointer:共有ポインタを使用するときに発生する巡回参照を処理するのに役立ちます。2つの共有ポインタが指し示す2つのオブジェクトがあり、共有ポインタが互いに共有ポインターを指している場合、巡回参照が存在し、共有ポインタが有効範囲外になると削除されます。 これを解決するには、内部メンバーをshared_ptrからweak_ptrに変更します。 注意:weakポインタが指す要素にアクセスするにはlock()を使います。これはweak_ptrを返します。

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

参照: std :: weak_ptrはいつ有用ですか?

ユニークポインタ:排他的所有権を持つ軽量スマートポインタ。 ポインタがオブジェクト間でオブジェクトを共有することなく、ポインタが一意のオブジェクトを指しているときに使用します。

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

ユニークなptrが指すオブジェクトを変更するには、move semanticsを使用します

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

参考文献:本質的にconstポインタ、すなわちconstであり、より良い構文では動かすことができないポインタであってもかまいません。

参照: C ++のポインタ変数と参照変数の違いは何ですか?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

参考: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ : https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQこの質問を指摘してくれたAndreに感謝しhttps://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ


スマートポインタは、ポインタのような型で、自動メモリ割り当て解除、参照カウントなどの機能を追加しています。

小さなイントロはページ上にありますスマートポインタ - 何、なぜ、どちら?

シンプルなスマートポインタ型の1つは、 std::auto_ptr (C ++標準の20.4.5章)です。スコープ外のときにメモリを自動的に解放し、例外がスローされたときの単純なポインタの使用よりも堅牢ですフレキシブル。

もう1つの便利な型はboost::shared_ptrこれは参照カウントを実装し、オブジェクトへの参照が残っていないときにメモリを自動的に解放します。 これはメモリリークを回避するのに役立ち、 RAIIを実装するのに使いやすいです。

件名はDavid Vandevoordeの「C ++ Templates:The Complete Guide」、Nicolai M. Josuttisの章、第20章「スマートポインタで詳しく説明されています。 一部のトピックでは、

  • 例外からの保護
  • ホルダー、(注意: std::auto_ptrは、この種のスマートポインタの実装です)
  • リソース獲得は初期化です (これはC ++での例外安全なリソース管理によく使用されます)
  • ホルダーの制限
  • 参照カウント
  • 同時カウンタアクセス
  • 破壊と解放

ほとんどの種類のスマートポインタは、あなたのためのオブジェクトへのポインタの処分を処理します。 これは、オブジェクトを手動で処理することをもう考えなくて済むので非常に便利です。

最も一般的に使用されるスマートポインタはstd::tr1::shared_ptr (またはboost::shared_ptr )であり、あまり一般的ではないが、 std::auto_ptrです。 私はshared_ptr定期的な使用をお勧めします。

shared_ptrは非常に汎用性があり、オブジェクトが「DLLの境界を越えて渡される」必要がある場合(コードとDLLの間で異なるlibcが使用される場合の一般的な悪夢の場合)など、さまざまな処分シナリオを扱います。


スマートポインタは、ポインタ自体が範囲外になり、それが指すものが削除される場合を除いて、 "char *"のような通常の(型付きの)ポインタのようなものです。 通常のポインタのように、 " - >"を使って使うことができますが、データへの実際のポインタが必要な場合は使用できません。 そのためには、 "&* ptr"を使用することができます。

これは以下の場合に便利です。

  • 新しいもので割り振られなければならないが、そのスタック上に何かと同じ生涯を持たせたいオブジェクト。 オブジェクトがスマートポインタに割り当てられている場合、その関数/ブロックを終了すると削除されます。

  • クラスのデータメンバー。オブジェクトが削除されると、所有者のデータもデストラクタに特別なコードがなくても削除されるようになります(デストラクタが仮想であることを確認する必要があります。 。

次の場合にスマートポインタを使用したくない場合があります。

  • ...ポインタは実際にデータを所有すべきではありません。つまり、単にデータを使用していても、ポインタを参照している関数にポインタを残しておく必要があります。
  • ...スマートポインタ自体はある時点で破壊されることはありません。 動的に割り当てられているが明示的に削除されないオブジェクトの中など、決して破壊されないメモリ内には置かないようにします。
  • ... 2つのスマートポインタが同じデータを指している可能性があります。 (ただし、それを処理するもっとスマートなポインタがあります。これは参照カウントと呼ばれます)。

参照:


スマートポインタは、メモリの割り当て解除、リソースの共有、転送について心配する必要のないものです。

これらのポインタは、Javaでの割り当てと同様に使用できます。 Javaのガベージコレクタではトリックを行いますが、スマートポインタではトリックはデストラクタによって行われます。


スマートポインタはクラスであり、通常のポインタのラッパーです。 スマートポイントのライフサークルは、通常のポインタとは異なり、参照カウント(スマートポインタオブジェクトが割り当てられている時間)に基づいています。 したがって、スマートポインタが別のスマートポインタに割り当てられると、内部参照カウントはプラスになります。 オブジェクトがスコープから外れると、参照カウントからマイナスが差し引かれます。

自動ポインタも同様に見えますが、スマートポインタとはまったく異なります。 これは、自動ポインタオブジェクトが可変スコープから出るたびにリソースの割り当てを解除する便利なクラスです。 ある程度までは、(動的に割り当てられたメモリへの)ポインタは、スタック変数(コンパイル時に静的に割り当てられる)と同様の働きをします。


同様の回答のリンクは次のとおりですhttp://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html : http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

スマートポインタは、通常のポインタのように動作し、外見や感触は向上しますが、より多くの機能を提供するオブジェクトです。 C ++では、スマートポインタは、ポインタをカプセル化して標準のポインタ演算子をオーバーライドするテンプレートクラスとして実装されています。 彼らは通常のポインタよりも多くの利点があります。 それらは、ヌルポインタまたはヒープオブジェクトへのポインタとして初期化されることが保証されています。 ヌルポインタによる間接参照がチェックされます。 削除は一切必要ありません。 オブジェクトへの最後のポインタがなくなると、オブジェクトは自動的に解放されます。 これらのスマートポインタの重要な問題の1つは、通常のポインタとは異なり、継承を尊重しないことです。 スマートポインタは多態性コードには魅力がありません。 スマートポインタの実装例を以下に示します。

例:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

このクラスは、タイプXのオブジェクトへのスマートポインタを実装します。オブジェクト自体はヒープ上にあります。 それを使用する方法は次のとおりです。

smart_pointer <employee> p= employee("Harris",1333);

他のオーバーロードされた演算子と同様に、pは通常のポインタのように動作し、

cout<<*p;
p->raise_salary(0.5);

最近のC ++の今日の簡単な答えは次のとおりです。

  • スマートポインタとは何ですか?
    値はポインタのように使うことができるが、自動メモリ管理の追加機能を提供する型です:スマートポインタがもはや使用されていないとき、それが指すメモリは割り当て解除されます( Wikipediaの詳細な定義も参照してください)。
  • いつ使うべきですか?
    コードでは、メモリの所有権を追跡すること、割り当てまたは割り当てを解除すること、 スマートポインタは、これらのことを明示的に実行する必要性を保存することがあります。
  • しかし、どのスマートポインタをこれらのケースで使うべきですか?
    • 同じオブジェクトへの複数の参照を保持するつもりがない場合は、 std::unique_ptr使用します。 たとえば、スコープを入力するときに割り当てられ、スコープを終了するときに割り当てが解除されるメモリへのポインタに使用します。
    • オブジェクトを複数の場所から参照したい場合は、 std::shared_ptr使用します。これらの参照がすべて消えるまで、オブジェクトを割り当て解除しないようにします。
    • 複数の場所からオブジェクトを参照したい場合は、 std::weak_ptr使用してください。無視したり解除したりすることができます(参照解除しようとするとオブジェクトがなくなったことに気付くでしょう)。
    • boost:: smartポインタやstd::auto_ptrは特別な場合を除いて使用しないでください。
  • ねえ、私はどちらを使うのか尋ねなかった!
    ああ、あなたは本当にしたいと思って、それを認めます。
  • だからいつ定期的なポインタを使うべきですか?
    主にメモリの所有権を知らないコードです。 これは通常、他の場所からポインタを取得し、その実行を引き継ぐポインタのコピーを割り当て、割り当て解除、または格納しない関数にあります。

私は上記の質問にもう一つの点を追加したいと思います。スマートポインタstd :: shared_ptrには添え字演算子がなく、ポンター演算をサポートしていません。get()を使って組み込みポインタを取得できます。







c++-faq