c++スマートポインタ(smart pointer)詳細


Smart Pointer
Deal with c++11’s smart pointer facility.
brief
Smart pointers are class objects that behave like built-in pointers but also manage objects that you create with new so that you don’t have to worry about when and whether to delete them - the smart pointers automatically delete the managed object for you at the appropriate time.
  • shared_ptr
  • weak_ptr
  • unique_ptr

  • shared_ptr(共有ポインタ)
  • referenced-counted smart pointer
  • Shared Ownership with shared_ptr

  • 参照カウントインテリジェントポインタ:他のboost::shared_ptrタイプのスマートポインタは所有権を共有します.この場合、参照オブジェクトの最後のスマートポインタが破棄されたり、再割り当てされたり、reset()が使用されたりすると、オブジェクトは解放されます.複数shared_ptrオブジェクトは同じオブジェクトを持つことができます.
    継承の例:
        shared_ptr base_ptr(new Thing(2));
        shared_ptr derived_ptr;
        ///if static_cast(base_ptr.get()) is valid, then the following is valid:
        base_ptr->showID();
    
        ///cast failed
        derived_ptr = static_pointer_cast(base_ptr);
    
        shared_ptr a(new Food);
    //    a->showID();
    
        derived_ptr->showID();
    

    make_の使用sharedの効率化
    There are actually two dynamic memory allocations that happen: one for the object itself from the new, and then a second for the manager object created by the shared_ptr constructor. Since memory allocations are slow, this means that creating a shared_ptr is slow relative to using either a raw pointer, or a so-called “intrusive” reference- counted smart pointer where the reference count is a member variable of the object. To address this problem, C++11 includes a function template make_shared that does a single memory allocation big enough to hold both the manager object and the new object, passing along any constructor parameters that you specify, and returns a shared_ptr of the specified type, which can then be used to initialize the shared_ptr that you are creating (with efficient move semantics).
    
        shared_ptr p(new Thing); // ouch - two allocations
        shared_ptr p1(make_shared()); // only one allocation!

    に注意
  • share_を使用ptr copy assignmentまたは構造関数はshared_ptrの参照カウントに1
  • を加算
  • reset()メンバー関数を使用して、現在のshare_を使用します.ptrは空であり、オブジェクトへのポインタ
  • を削除する.
  • はshare_に通過しましたptr付与nullptrは、第2条の効果
  • を達成することができる.
  • 原生ポインタとスマートポインタとの間の直接付与変換
  • は許可する.
  • オリジナルポインタから2つの機能が同じsmart pointerを直接構築しないでください.そうしないとdouble-deletionエラー
  • になります.
  • はget()関数により原生ポインタ
  • を得ることができる.
  • 関係またはその他の変換を継承する場合に使用できます.
  • static_pointer_cast
  • dynamic_pointer_cast
  • const_pointer_cast


  • weak_ptr
    Weak pointers just “observe” the managed object; they don’t “keep it alive” or affect its lifetime. Unlike shared_ptrs, when the last weak_ptr goes out of scope or disappears, the pointed-to object can still exist because the weak_ptrs do not affect the lifetime of the object - they have no ownership rights. But the weak_ptr can be used to determine whether the object exists, and to provide a shared_ptr that can be used to refer to it.
    管理対象オブジェクトのみを観察し、ライフサイクルに影響を与えません.
    1.weak_ptr build-in-pointer might zero.
    void do_it(weak_ptr wp){
    shared_ptr sp = wp.lock();
    // get shared_ptr from weak_ptr 
            if(sp)
              sp->defrangulate(); // tell the Thing to do something
            else
              cout << "The Thing is gone!" << endl;
    }

    2.This approach is useful as a way to simply ask whether the pointed-to object still exists.
     bool is_it_there(weak_ptr wp) {
           if(wp.expired()) {
              cout << "The Thing is gone!" << endl;
              return false;
              }
           return true;
       }
    

    3.if the weak_ptr is expired, an exception is thrown, of type std::bad_weak_ptr.
    
    void do_it(weak_ptr wp){
    shared_ptr sp(wp); // construct shared_ptr from weak_ptr
     // exception thrown if wp is expired, so if here, sp is good to go sp->defrangulate();
      // tell the Thing to do something
    }
       try {
              do_it(wpx);
           }
           catch(bad_weak_ptr&)
           {
              cout << "A Thing (or something else) has disappeared!" << endl;
           }

    4.inherit from enabled_shared_from_this\
    エラーが発生しない場合error:pointer being freed was not allocated
    class Thing:public enable_shared_from_this{
    public:
        int id;
    public:
        virtual void showID() const;
        Thing();
        Thing(int _id);
        void foo();
    
    };
    void Thing::foo() {
        shared_ptr t1 = shared_from_this();
        t1->showID();
    
    }

    公有継承enable_shared_from_Thingクラスにweakがありますptrはメンバー変数として使用されます.最初のshared_ptrが作成されると、最初のshared_からptrでweakを初期化ptr、thisを指すshareが必要な場合ptr時にshared_を呼び出すfrom_this()メンバー関数、weakによって返されます.prt構築されたshared_ptrは、返されるshared_ptrと初めてのshared_ptrは同じmanage objectです.
    に注意
  • weak_ptrとshare_ptrを組み合わせて使用し、share_からのみptrのレプリケーションと付与、またはソースと他のweak_ptr.
  • lock()関数検査weak_ptrが指すオブジェクトが存在するかどうか、存在しない場合は空のshareを返します.ptr、そうでなければオブジェクトを指すshare_を返します.ptr.
  • weakには使用できません.ptrがnullptrを付与する方法はreset()メソッド
  • のみである.
  • expired()関数はweakを返します.ptrが空でないオブジェクトが存在するかどうか.
  • 構造関数ではshared_を使用できません.from_this
  • できるだけ多くの組み合わせでshareを使用します.ptrとweak_ptr、メモリ管理を自動化します.

  • unique_ptr
    With a unique_ptr, you can point to an allocated object, and when the unique_ptr goes out of scope, the pointed-to object gets deleted, and this happens regardless of how we leave the function, either by a return or an exception being thrown somewhere.
    unique_ptr implements a unique ownership concept - an object can be owned by only one unique_ptr at a time - the opposite of shared ownership.
    unique_ptrはcopyコンストラクション関数とcopy assignmentオペレータを暗黙的に削除し、1つのオブジェクトが同時に複数のunique_ptrが持っているのはshared_ptrは逆です.
    The unique ownership is enforced by disallowing (with =delete) copy construction and copy assignment.So unlike built-in pointers or shared_ptr, you can’t copy or assign a unique_ptr to another unique_ptr.
    move semantics: the move constructor and move assignment operator are defined for unique_ptr so that they transfer ownership from the original owner to the new owner.
    moveコンストラクション関数とmove assignmentオペレータでunique_を作成できます.ptrの所属権は元のものから新しいものに移行する.転送後の元のunique_ptrにはオブジェクトは含まれません.
    暗黙的な右からの変換
     unique_ptr create_Thing()
       {
           unique_ptr local_ptr(new Thing);
           return local_ptr;  // local_ptr will surrender ownership
       }
    void foo() {
           unique_ptr p1(create_Thing()); // move ctor from returned rvalue
            // p1 now owns the Thing
            unique_ptr p2; // default ctor'd; owns nothing
            p2 = create_Thing(); // move assignment from returned       rvalue // p2 now owns the second Thing
    }

    move assignmentとmove constructionを明示的に使用して変換
    unique_ptr<Thing> p1(new Thing); // p1 owns the Thing
    unique_ptr<Thing> p2; // p2 owns nothing
    // invoke move assignment explicitly
    p2 = std::move(p1); // now p2 owns it, p1 owns nothing
    // invoke move construction explicitly
    unique_ptr<Thing> p3(std::move(p2)); // now p3 owns it, p2 and p1 own nothing 

    に注意
  • reset()関数またはunique_ptrはnullptrを割り当て、手動でオブジェクトを削除できます.

  • reference
    c++11 smart pointer