C++智能指標(二):類比實現三種智能指標__C++

來源:互聯網
上載者:User

上一篇部落格我們簡單介紹了智能指標:簡單介紹智能指標

有關shared_ptr的循環參考問題可以參考部落格:weak_ptr–解決shared_ptr循環參考問題 auto_ptr 類比實現

template<class T>class Autoptr{public:    Autoptr(T* ptr = NULL)        :_ptr(ptr)    {}    Autoptr(Autoptr<T>& ap)    {        _ptr = ap._ptr;        ap._ptr = NULL;    }    Autoptr<T>& operator=(Autoptr<T>& ap)    {        if (this != &ap)        {            delete _ptr;            _ptr = ap._ptr;            ap._ptr = NULL;        }        return *this;    }    T* operator->()    {        return _ptr;    }    T operator*()    {        return *_ptr;    }    ~Autoptr()    {        delete _ptr;        _ptr = NULL;    }    void Reset(T* ptr = 0)    {        if (_ptr != ptr)        {            delete _ptr;        }        _ptr = ptr;    }protected:    T* _ptr;};void APTest(){    Autoptr<int> ap1(new int(10));    cout <<"*ap1 = "<< *ap1 << endl;    Autoptr<int> ap2(ap1);    cout <<"*ap2 = "<< *ap2 << endl;    Autoptr<int> ap3(new int(20));    ap3 = ap2;    cout <<"*ap3 = "<< *ap3 << endl;    //cout << *ap1 << endl;//報錯}

測試結果:
程式碼分析

代碼中的Reset()函數是幹嘛的。

void Reset(T* ptr = 0)    {        if (_ptr != ptr)        {            delete _ptr;        }        _ptr = ptr;    }

答:為了重設一個auto_ptr對象,必須使用reset()函數。可以向reset()傳遞一個指標,如果不希望設定該auto_ptr對象的話,可以傳遞一個0值。如果auto_ptr當前指向一個對象並且該auto_ptr對象擁有該對象的所有權,則該對象再底層指標重設之前,首先被刪除。例如:

void APTest(){    int *pi = new int(20);    auto_ptr<int>_auto_ptr(pi);    cout << "_auto_ptr = " << *pi << endl;    int *pi2 = new int(30);    _auto_ptr.reset(pi2);    cout << "pi->" << *pi << endl;    cout << "pi2->" << *pi2 << endl;}

輸出結果:

我們可以在輸出結果的第二行看到,pi已經變成了隨機值。reset()函數將auto_ptr對象原來指向的那塊動態分配的空間釋放了。

上面的代碼還有一句:

//cout << *ap1 << endl;//報錯

為什麼報錯。。
這是因為ap1已經把它指向的空間交給了ap2去管理,所以ap1已經不具備訪問原來自己所指向的空間的許可權。所以對它進行解引用是非法的。
所以可以看清auto_ptr的本質是管理權的轉移,即ap1將自己所指向的空間交給ap2來管理,析構也是由ap2來完成。 scoped_ptr

由於auto_ptr的嚴重缺陷,所以後來引入了scoped_ptr。防拷貝,意思就是不能進行拷貝,簡單地說是一種簡單粗暴的方式。 類比實現

template<class T>class  Scopedptr{public:    Scopedptr(T* ptr = NULL)        :_ptr(ptr)    {}    T* operator->()    {        return _ptr;    }    T operator*()    {        return *_ptr;    }    ~Scopedptr()    {        delete _ptr;        _ptr = NULL;    }protected:    Scopedptr(Scopedptr<T>& sp);    Scopedptr<T>& operator=(const Scopedptr<T>& p);private:    T* _ptr;};void SPTest(){    Scopedptr<int> sp(new int(10));    cout << "sp = " << *sp << endl;}

scoped_ptr中對拷貝建構函式和賦值運算子的重載函數只是進行了聲明,並沒有去定義這兩個函數,而且聲明為protected或者是private,這是防止別人在類外對這兩個函數進行定義。防止拷貝,所以說scope_dptr是一種簡單粗暴的方式。 shared_ptr

編寫程式往往要用到拷貝,這樣scopedptr就不能起到相應的作用,所以便有了shared_ptr。
shared_ptr->採用了引用計數,優點是功能強大,但是也有缺點,缺點是過於複雜,而且會引起循環參考。

template<class T>class Sharedptr{public:    Sharedptr(T* ptr = NULL)        :_ptr(ptr)        , pcount(0)    {        if (_ptr != NULL)            pcount = new int(1);    }    Sharedptr(const Sharedptr<T>& sp)    {        _ptr = sp._ptr;        pcount = sp.pcount;        ++(*pcount);    }    Sharedptr<T>& operator=(const Sharedptr<T>& sp)    {        if (this != &sp)        {            if (_ptr && --(*pcount) == 0)            {                delete pcount;                delete _ptr;            }            pcount = sp.pcount;            _ptr = sp._ptr;            ++(*pcount);        }        return *this;    }    ~Sharedptr()    {        if (_ptr && --(*pcount) == 0)        {            delete _ptr;            delete pcount;        }    }    T& operator*()    {        return *_ptr;    }    T* operator->()    {        return _ptr;    }    T Getpcount()    {        return *(pcount);    }    void Realease()    {        if (--(*pcount) == 0)        {            delete _pcount;            delete _ptr;        }    }    void Reset(T* ptr, int* pcount)    {        if (_ptr != ptr)        {            delete _ptr;            delete _pcount;        }        _ptr = ptr;        _pcount = pcount;    }private:    T* _ptr;    T* pcount;};void Test(){    Sharedptr<int> s1(new int(10));    cout << "s1 = " << *s1 << endl;    cout << "pcount = " << s1.Getpcount() << endl;    Sharedptr<int> s2(s1);    cout << "s2 = " << *s2 << endl;    cout << "pcount = " << s2.Getpcount() << endl;    Sharedptr<int> s3;    s3 = s1;    cout << "s3 = " << *s3 << endl;    cout << "pcount = " << s3.Getpcount() << endl;}

測試結果:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.