enable_shared_from_this

5935 ワード

enable_shared_from_this(転載)
C++では自分でメモリを処理する必要がありますが、少し処理が適切でないと、非常に憂鬱なメモリ漏れの問題があります.
 
幸いなことに、C++では強力なスマートポインタ、すなわちsmartが発売されています.ptr、本稿ではsmartを少し紹介します.ptr、そして具体的にshared_ptrとweak_ptr、特にenable_shared_from_thisとshared_from_this
 
標準ライブラリのauto_を除くptr以外
boostまたはtr 1のsmart_ptrは主に次のようなものがあります
  • scoped_ptr
  • scoped_array
  • shared_ptr
  • shared_array
  • intrusive_ptr
  • weak_ptr

  • これらの中で最も理解しにくいのはweakを総合的に応用したことです.ptrとshared_ptrのenable_shared_from_このクラスにはメンバー関数shared_が定義されていますfrom_これは、shared_を返します.ptr .この関数はshared_のみですptrのコンストラクション関数が呼び出されてから使用できます.なぜならenable_shared_from_this::weak_ptrは、コンストラクション関数に設定されるのではなく(ここでのコンストラクション関数とは、タイプTのコンストラクション関数を指す)、shared_ptrのコンストラクション関数に設定される(ここでのコンストラクション関数とは、タイプshared_ptrのコンストラクション関数を指す).
     
    次のコードで、
     
    Cppコード
  • #include    
  •   
  • #include    
  •   
  •     
  •   
  • #include    
  •   
  • #include    
  •   
  • #include    
  •   
  •     
  •   
  • using namespace std;   
  •   
  •     
  •   
  • struct Ansible   
  •   
  •   : public boost::enable_shared_from_this   
  •   
  • {   
  •   
  •     boost::shared_ptr get_shared()   
  •   
  •     {   
  •   
  •         boost::shared_ptr r(this);   
  •   
  •     
  •   
  •         return r;   
  •   
  •     }   
  •   
  •     
  •   
  •     ~Ansible()   
  •   
  •     {   
  •   
  •         cout<<"Destructor"<
  •   
  •     }   
  •   
  • };   
  •   
  •     
  •   
  • int main(int argc,char* argv[])   
  •   
  • {   
  •   
  •     boost::shared_ptr a(new Ansible);   
  •   
  •     Ansible& r = *a;   
  •   
  •     //boost::shared_ptr b = r.get_shared();   
  •   
  •     boost::shared_ptr b = r.shared_from_this();   
  •   
  •     
  •   
  •     cout<<"Reference Number "<
  •   
  •     
  •   
  •     return 0;   
  •   
  • }  
  • #include <iostream> #include <string> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/enable_shared_from_this.hpp> using namespace std; struct Ansible : public boost::enable_shared_from_this<Ansible> { boost::shared_ptr<Ansible> get_shared() { boost::shared_ptr<Ansible> r(this); return r; } ~Ansible() { cout<<"Destructor"<<endl; } }; int main(int argc,char* argv[]) { boost::shared_ptr<Ansible> a(new Ansible); Ansible& r = *a; //boost::shared_ptr<Ansible> b = r.get_shared(); boost::shared_ptr<Ansible> b = r.shared_from_this(); cout<<"Reference Number "<<a.use_count()<<" "<<b.use_count()<<endl; return 0; }

     
    shared_を使用しない場合from_this()メンバー関数は、aとbのuse_を出力します.count()はすべて1で、それから2回のタイプAnsibleの構造関数を呼び出して、もしこのメンバー関数を追加したら、aとbのuse_count()出力は2であり,Ansibleの構造関数を1回呼び出すだけである.なぜならenable_shared_from_この中はshared_ptrの時にweakを構築しましたptrクラス、weak_ptrは監視のみで、参照カウントは増加しません
     
    (以下、転載:http://huyuguang1976.spaces.live.com/blog/cns!2A9E272E3C33AFF1!185.entry )
    次のコードは間違っています.
     
    class D:public boost::enable_shared_from_this
    {
    public:
        D()
        {
            boost::shared_ptr p=shared_from_this();
        }
    };
     
    理由は簡単で、Dの構造関数ではenable_が保証されていますがshared_from_thisのコンストラクション関数が呼び出されましたが、前述したようにweak_ptrはまだ設定されていません.
     
    次のコードもエラーです.
     
    class D:public boost::enable_shared_from_this
    {
    public:
        void func()
        {
            boost::shared_ptr p=shared_from_this();
        }
    };
     
    void main()
    {
        D d;
        d.func();
    }
     
    エラーの原因は同じです.
     
    次のコードが正しいです.
     
    void main()
    {
        boost::shared_ptr d(new D);
        d->func();
    }
     
    ここでboost::shared_ptrd(new D)は実際に3つの動作を実行した:まずenable_を呼び出すshared_from_thisのコンストラクション関数;次にDのコンストラクタを呼び出す.最後にshared_を呼び出すptrのコンストラクション関数.3番目のアクションにenableが設定されています.shared_from_こののweak_ptrは、1番目の動作ではありません.ここはc++の常識と論理に反しているので、気をつけなければなりません.
     
    結論として、構造関数でshared_を使用しないでください.from_this ;次にshared_を使用する場合ptrは,すべての場所で使用すべきであり,D dという方式は使用できず,裸のポインタも決して渡さない.別解::::struct X
    {
             boost::shared_ptr getX()
    {
             boost::shared_ptr r ;//????実装方法
             return r;
    }
    };
     
    Xのスマートポインタを得るには、オブジェクトポインタがshared_を受けるだけです.ptr保護に基づいて、例えば以下のようにする.
    void test_X()
    {
             {
    X x;
                      boost::shared_ptr px = x.getX();//エラー
    }
             {
    X* x = new X();
    boost::shared_ptr px = x->getX();//エラー
    }
             {
    boost::shared_ptr  x (new X());
    boost::shared_ptr px = x->getX();//正しい
    }
    }