C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).

6870 ワード

目次
  • C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).
  • auto_ptr
  • scoped_ptr
  • ptr_vector

  • C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).
    前言
    最近muduoの非同期ログをもう1つ書いて多くのスマートポインタに触れたが、boostライブラリを使うつもりはなく、1つ型を作って使うしかなかった. .
    インテリジェントポインタ自体はスタック上に作成するオブジェクトであり、構築時にスタック上のリソースを割り当て、構築時にリソースを解放することで、スタック上のデータリソースの漏洩を回避することができる.同時にリロードする->演算子と*演算子は、裸のポインタのような操作を実現する.
    いくつかのローカルスマートポインタオブジェクトの実装コードを見てみましょう.
    auto_ptr
    auto_ptrの特徴:コピー構造関数を実現し、=演算子を再ロードし、->、*演算子を実現し、通常のポインタのように使用できるようにするとともにrelease()とreset()法により安全な転送使用権を実現する.
    #ifndef _AUTO_PTR_HH
    #define _AUTO_PTR_HH
    
    template
    class auto_ptr{
    public:
        explicit auto_ptr(T* p = 0):m_ptr(p){printf("1
    "); } auto_ptr(auto_ptr& obj):m_ptr(obj.release()){printf("2
    "); } auto_ptr& operator=(auto_ptr& obj){printf("3
    "); reset(obj.release()); return *this; } ~auto_ptr(){printf("4
    "); delete m_ptr; } T* release(){ T* tmp = m_ptr; m_ptr = 0; return tmp; } void reset(T* p){ if(m_ptr != p) delete m_ptr; m_ptr = p; } T* get() const { return m_ptr; } T* operator->(){ return get(); } T& operator*(){ return *get(); } private: T* m_ptr; }; #endif

    テストコード:
    #include "ScopePtr.hh"
    #include "auto_ptr.hh"
    #include 
    
    class NonCopyable
    {
    protected: //            ,         
        NonCopyable() {printf("Nocopy Constroctr
    ");} ~NonCopyable() {printf("~Nocopy DeConstroctr
    ");} private: NonCopyable(const NonCopyable &); const NonCopyable &operator=(const NonCopyable &); }; class Test// : private NonCopyable{ {public: Test(){printf("Constroctr
    ");} ~Test(){printf("~DeConstroctr
    ");} }; int main(){ //scoped_ptr st(new Test); auto_ptr ap1(new Test); auto_ptr ap2(new Test); auto_ptr ap3(ap2); ap2 = ap3; getchar(); return 0; }
    Constroctr
    1
    Constroctr
    1
    2
    3
    
    4
    4
    ~DeConstroctr
    4
    ~DeConstroctr
    

    scoped_ptr
    これはboostライブラリの中のもので、auto_とptrは正反対:コピー構造と=リロードをすべてプライベートに構成する、所有権の移転を許さない目的を達成した.
    #ifndef _SCOPE_PTR_HH
    #define _SCOPE_PTR_HH
    //  scoped_ptr mimics a built-in pointer except that it guarantees deletion
    //  of the object pointed to, either on destruction of the scoped_ptr or via
    //  an explicit reset(). scoped_ptr is a simple solution for simple needs;
    //  use shared_ptr or std::auto_ptr if your needs are more complex.
    
    /*
    scoped_ptr                 。
    */
    template 
    class scoped_ptr
    {
    public:
        scoped_ptr(T *p = 0) :m_ptr(p) {
        }
        
        ~scoped_ptr(){
            delete m_ptr;
        }
        
        T&operator*() const {
            return *m_ptr;
        }
        
        T*operator->() const {
            return m_ptr;
        }
        
        void reset(T *p)//                            
        {
            if (p != m_ptr && m_ptr != 0)
                delete m_ptr;
            m_ptr = p;
        }
    
        T* get(){
            return m_ptr;
        }
    
    private://                           
        //       ,                           
        scoped_ptr(const scoped_ptr &y);
        scoped_ptr operator=(const scoped_ptr &);
        void operator==(scoped_ptr const &) const;
        void operator!=(scoped_ptr const &) const;
    
        T* m_ptr;
    };
    
    #endif

    ptr_vector
    これもboostの中のもので、もし私たちがオブジェクトポインタをvectorの中に置くだけで、容器が析出するときは自分で開いたポインタを格納する空間を析出するが、ポインタ自体が指す空間を析出することはなく、この容器がある.
    #ifndef _PTR_VECTOR_HH
    #define _PTR_VECTOR_HH
    
    #include "auto_ptr.hh"
    #include 
    
    template
    class ptr_vector : public std::vector{
    public:
        ~ptr_vector(){
            clear();
        }
    
        void clear(){
            typename std::vector::iterator it;
            for(it = std::vector::begin(); it != std::vector::end(); ++it){
                delete *it;//         .
            }
            
            /*
            for(size_t i = 0; i < std::vector::size(); ++i){
                delete std::vector::back();
            }*/
            
            std::vector::clear(); //      .
        }
    
        typename std::vector::iterator erase(typename std::vector::iterator it){
            if(it >= std::vector::begin() && it < std::vector::end()){
                delete *it;
                std::vector::erase(it);
            }
        }
    
        void pop_back(){
            if(std::vector::size() > 0){
                delete std::vector::back();
                std::vector::pop_back();
            }
        }
        
        void push_back(T* const &v){
            auto_ptr ap(v);
            std::vector::push_back(v);
            ap.release();
        }
    
        void push_back(auto_ptr &v){
            std::vector::push_back(v.get());
            v.release();
        }
        
    };
    
    #endif

    テストコード:
    
    class Test// : private NonCopyable{
    {public:
        Test(int a = 99):a(a){printf("Constroctr
    ");} ~Test(){printf("~DeConstroctr
    ");} int get(){return a;} private: int a; }; int main(){ auto_ptr ap1(new Test(0)); auto_ptr ap2(new Test(1)); auto_ptr ap3(new Test(2)); printf("%d
    ", ap1->get()); ptr_vector apv; apv.push_back(ap1); apv.push_back(ap2); apv.push_back(ap3); printf("%d %lu
    ", apv.front()->get(),apv.size()); /* apv.pop_back(); printf("%lu
    ", apv.size()); apv.pop_back(); printf("%lu
    ", apv.size()); apv.pop_back(); printf("%lu
    ", apv.size()); */ apv.pop_back(); printf("%lu
    ", apv.size()); ptr_vector::iterator it = apv.begin(); apv.erase(it); printf("%lu
    ", apv.size()); getchar(); return 0; }
    Constroctr
    Constroctr
    Constroctr
    0
    0 3 
    ~DeConstroctr
    2
    ~DeConstroctr
    1
    
    ~DeConstroctr

    本文は主にスマートポインタの本質を紹介し、二つの簡単なスマートポインタの実現と一つのポインタ容器の実現を紹介した.
    実は今auto_ptrはあまり使われていませんが、元のポインタを処理していないと、移行後、元のポインタが空になり、誰かが使用すると問題になります.vectorにも多くの問題がありますpop_back()は空の容器で、vectorの中で同じようにします--size、この时容器の大きさは0から无限に大きくなって、结果は予想できません、.本例では、このような場合を処理する.pop_back()空のvectorは何もしません.しかしvectorの使い方にはこだわりがある.そうしないと問題になりやすい.
    転載先:https://www.cnblogs.com/ailumiyana/p/9451761.html