模擬實現智能指針auto_ptr,scoped_ptr,shared_ptr

智能指針,顧名思義它是一個聰明的指針,那麼到底聰明到哪了呢,讓我們一起來看以下的代碼。

void test1()   //內存泄露
{
    int *p = new int(1);
    if (1)
    {
        //...
        return;
    }
    //...
    //...
    delete p;
}

智能指針就是可以自動化地管理指針所指向的動態內存的釋放。

  1. STL---AutoPtr (管理權轉移,不推薦使用)包含在頭文件 #include<memory>中。

新方案:(管理權轉移)std::auto_ptr 能夠方便的管理單個堆內存對象。

template<class T>
class AutoPtr  //管理權轉移
{
public:
    AutoPtr(T *ptr)  
        :_ptr(ptr)
    {}
    ~AutoPtr()
    {
        if (_ptr == NULL)
        {
            cout << "delete:" << _ptr << endl;
            delete _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;
    }
protected:
    T *_ptr;
};

舊方案:(在某些情況下,會產生野指針)

思路:在新方案的基礎上,新增一個bool變量(_owner),只要_owner爲true,才析構,不再通過將賦值的值置空。

template<class T>
class AutoPtr
{
public:
    AutoPtr(T *ptr)
        :_ptr(ptr)
        , _owner(true)
    {}
    ~AutoPtr()
    {
        if (_owner == true)
        {
            delete _ptr;
        }
    }
    AutoPtr( AutoPtr<T>& ap)
        :_ptr(ap._ptr)
        , _owner(ap._owner)
    {
        ap._owner = false;
    }
    AutoPtr<T>& operator=(AutoPtr<T>& ap)
    {
        if (this != &ap)
        {
            delete _ptr;
            _ptr = ap._ptr;
            _owner = ap._owner;
            ap._owner = false;
        }
        return *this;
    }
protected:
    T *_ptr;
    bool _owner;
};
void test1()
{
    AutoPtr<int> ap1(new int(1));
    AutoPtr<int> ap2(ap1);
    AutoPtr<int> ap3(new int(2));
    ap3 = ap2;
}

2. boost—ScopedPtr(防拷貝。簡單、粗暴,只定義,不實現)

template<class T>
class ScopedPtr   //必須需要的1.聲明,2.保護類型
{
public:
    ScopedPtr(T *ptr)
        :_ptr(ptr)
    {}
    ~ScopedPtr()
    {
        if (_ptr == NULL)
        {
            delete _ptr;
        }
    }
    T & operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
protected:  //protected:防止別人搞破壞行爲
    ScopedPtr( ScopedPtr<T> &sp);
    ScopedPtr<T>& operator=(ScopedPtr<T> &sp);
protected:
    T *_ptr;
};

3. boost—SharedPtr(引用計數的方法實現)

template<class T>
class SharedPtr   //引用計數
{
public:
    SharedPtr(T *ptr)
        :_ptr(ptr)
        , _pcount(new int(1))
    {}
    ~SharedPtr()
    {
        if (--(*_pcount)==0)
        {
            delete _ptr;
            delete _pcount;
        }
    }
    SharedPtr(const SharedPtr<T> &sp)
        :_ptr(sp._ptr)
        , _pcount(sp._pcount)
    {
        ++(*_pcount);
    }

    SharedPtr<T>& operator=(const SharedPtr<T>& sp)
    {
        if (_ptr != sp._ptr) //防止自賦值和同時管理同一塊空間
        {
            if (--(*_pcount) == 0)
            {
                delete _ptr;
                delete _pcount;
            }
            _ptr = sp._ptr;
            _pcount = sp._pcount;
            ++(*_pcount);
        }
        return *this;
    }
    T& operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
protected:
    T *_ptr;
    int *_pcount;
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章