インテリジェントポインタとその役割

4194 ワード

一、導入背景
C++のポインタを使用すると、メモリ領域を動的に開くことができますが、使用後に解放を忘れる(または解放前にプログラムthrowがエラーを起こし、解放されない)と、プログラムが終了するまでメモリユニットが占有され続け、いわゆるメモリリークが発生します.【注】メモリ漏洩とは、スタックメモリの漏洩をいう.スタックは、newによって割り当てられたメモリブロックです.したがって,スマートポインタの役割は,スタック上のオブジェクトを使用する場合,オブジェクトが必ず解放されることを保証するためであるが,一度だけ解放され,解放後にそのオブジェクトを指すポインタはすぐに0に戻るべきである.
二、C++11以前のスマートポインタ
auto_ptrは、動的に割り当てられたオブジェクトポインタを指し、その構造関数は、オブジェクトの生存期間の制御を達成するために、オブジェクトの空間を削除するために使用される.次の理由で廃棄されました.
  • 潜在的なメモリクラッシュの回避:auto_ptrが付与操作を行う場合、付与されたものはその所有権を取得し、付与されたものはその所有権を失う(空のポインタになり、これ以上使用できない).
  • は便利ではありません:移動の意味がありません(後述).

  • 三、C++11標準のスマートポインタ
    uniqueに参加しましたptr、shared_ptrとweak_ptr.
  • unique_ptr、boostライブラリのscoped_に等しいptr、名前の通りscoped_ptrが指すオブジェクトは,役割ドメインの外で自動的に解析される.【注】boostライブラリは、BoostコミュニティがC++11以前に標準更新が遅すぎることを嫌って、自発的に開発、メンテナンスを組織する拡張ライブラリである.ヘッダファイル”boost/scoped_ptr.hpp”を含むことによって導入される.単純定義:
  • namespace boost
    {
        // scoped_ptr   non-copyable  
        //                scoped_ptr          scoped_ptr  
        //                          
        template class scoped_ptr : noncopyable
    
        {
        private:
    
            T *px;
                                                 
            // scoped_ptr        scoped_ptr      
            //     scoped_ptr              =          private
            scoped_ptr(scoped_ptr const &);
            scoped_ptr &operator=(scoped_ptr const &);
    
            typedef scoped_ptr this_type;
    
            void operator==( scoped_ptr const & ) const;
            void operator!=( scoped_ptr const & ) const;
    
        public:
    
            //         ,        (      =)  
            explicit scoped_ptr(T *p = 0);
            ~scoped_ptr();
    
            explicit scoped_ptr( std::auto_ptr p ): px( p.release() );
            //   scoped_ptr                       ,     reset     
            void reset(T *p = 0);
    
            T &operator*() const;
            T *operator->() const;
            T *get() const;
    
            //    scoped_ptr        ,           
            void swap(scoped_ptr &b);
        };
    
        template
        void swap(scoped_ptr &a, scoped_ptr &b);
    }
    
  • shared_ptr、ポインタオブジェクトを共有でき、shared_に値を割り当てることができます.ptrまたはweak_ptr.shared_ptrで実現される本質は参照カウントであり、shared_をコピーすることである.ptrは、このスマートポインタの参照回数に1を加算し、このスマートポインタの参照回数を0に下げると、オブジェクトが自動的に解析される.コードセクションとscoped_ptrは似ていますが、コピー、割り当て、==、!=をサポートします.
  • weak_ptr weak_ptrとshared_ptrの最大の違いはweak_ptrはオブジェクトを指すときに参照カウントを増加させないのでweak_ptrはオブジェクトを指しweak_ptrはまだこのオブジェクトを指している間にそれを解析し、weakにアクセスします.ptrの時、weak_ptrは空のsharedを返しますptr. リングリファレンスの問題を解決するためによく使われ、C++リングのどのリファレンスが最も弱いかを教えるため、1つのリングで元のshared_をptrをweak_に変更ptrでいいです.

  • 【注】以上のstd標準ライブラリのスマートポインタは、ヘッダファイルを含むことによって導入することができる.
    四、スマートポインタunique_ptrとshared_ptrの使用選択
    違いは知ってるuniqueptrは、指向するオブジェクトを独占する、すなわち、ある時点でunique_が1つしか存在しないptrは、所与のオブジェクトを指します.このオブジェクトを複数のポインタで共有する必要がある場合は、shared_に変換できます.ptr.uniqueの場合ptrは、破棄されると、その指向するオブジェクトも破棄されます.でもshared_ptrは参照カウント(use_count)を維持し、最後のshared_のみを維持します.ptrも破棄されたとき、このオブジェクトは本当に破棄されます.
    シーンを使用shared_ptrは強力ですが、shared_をいつでも使用する必要はありません.ptr.使用するポインタが所有権を共有されているかどうか分からない場合は、デフォルトでunique_を選択します.ptr独占所有権、unique_ptr効率比shared_ptrは高く、参照カウントと背後の制御ブロックを維持する必要はありません.共有されると判断したらshared_に変換できますptr.
    また、2つのポインタが同じ変数を共有するにはshared_が必要だというわけではありません.ptr,特にマルチスレッドに関与しないプログラムでは,スマートポインタを使用しなくても構わない.
    shared_を使う必要があるptrのシーンの例:
    ----------------------------------------
    |               Thread 1               |
    | ------------------------------------ |
    | void func(shared_ptr p) { ... } |
    ----------------------------------------
    
    -------------------------------------------
    |              Main Thread                |
    | --------------------------------------- |
    | shared_ptr p = make_shared(); |
    | func(p);                                |
    -------------------------------------------
    

    メインスレッドはサブスレッドを開き、スマートポインタshared_を使用しない場合はfunc関数を実行します.ptrは、メインスレッドの実行が完了すると、通常のポインタpが自動的に解放され、サブスレッドの関数がまだ実行されていないうちに、pが失効し、プログラムがクラッシュする.shared_を使用ptrは、プライマリスレッドの終了時にのみ自動的にuse_をcountは1つ減らして、サブスレッドの使用に影響しません.
    参考文献:[1]shared_ptrとunique_ptr区別と連絡[2]スマートポインタ:shared_ptrとunique_ptr、unique_を優先的に使用ptr