智能指針發展

智能指針就是智能/自動化的管理指針所指向的動態資源的釋放。並且可以向指針一樣使用。

1、早期auto_ptr—是一種失敗的設計,有設計缺陷

爲了解決對象中指針的重複釋放,採用管理權轉移的方式。

即在解決對象的賦值、拷貝構造時,比如:a = b;將a的地址空間釋放,然後將b.ptr的指針賦給a.ptr,最後將地址空間的管理權交付於a.ptr,並將b.ptr致null。因此,在賦值過後,將不能使用原來指針,缺點就是不能有幾個指針指向同一塊內存,一個智能指針只能指向一塊內存。

下面我們可以模擬auto_ptr

#include <iostream>
using namespace std;

template <typename T>            //管理權轉移法
class AutoPtr
{
public:
    AutoPtr(T* ptr = NULL)
        :_ptr(ptr)
    {}
    AutoPtr(AutoPtr<T>& ap)        //拷貝構造
        :_ptr(ap._ptr)
    {
        delete ap->_ptr;
    }
    AutoPtr<T>& operator=(AutoPtr<T>& ap)  //賦值運算符重載
    {
        if (this != &ap) // this->_ptr= ap.ptr
        {
            delete _ptr;
            this->_ptr = ap._ptr;
            ap._ptr = NULL;
        }
        return *this;
    }
    T& operator*()const 
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
    ~AutoPtr()
    {
        if (NULL != _ptr)
        {
            delete _ptr;
            _ptr = NULL;
        }
    }
private:
    T* _ptr;
};

class AA
{
public:
    int a;
    int b;
};
void funtest1()
{
    AutoPtr<AA> ap1(new AA);
    (*ap1).a = 10;
    (*ap1).b = 20;
    ap1->a = 30;
    ap1->b = 40;
}
void funtest2()
{
    AutoPtr<int> ap3(new int[10]);
    AutoPtr<int> ap4(new int[5]);
    ap3 = ap4;
} 
int main()
{
    //funtest1();
    funtest2();
    system("pause");
    return 0;
}

2.發展期:在使用時期,開發者逐漸發現auto_ptr的不足,於是有一些開發者逐漸放棄auto_ptr並且自主實現auto_ptr功能,例如scoped_ptr/share_ptr/week_ptr

1 scoped_ptr在實現智能指針時採用簡單粗暴的方式,採用仿函數,在外部不允許使用,不允許進行拷貝構造函數和賦值運算符重載。

scoped的模擬實現:

template<class T>
class ScopedPtr
{
public:
    ScopedPtr(T* ptr = NULL)
        :_ptr(ptr)
    {}
    ~ScopedPtr()
    {
        if (_ptr)
        {
            delete _ptr;
        }
    }
    T& operator*()
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
private:
    ScopedPtr(const ScopedPtr<T>& sp);         // 1.只聲明不定義
    ScopedPtr<T>& operator=(const ScopedPtr<T>&);          // 2.聲明成私有

protected:
    T* _ptr;
};

share_ptr採用引用技術思想,在對象構造時記下使用次數,到最後只有一個使用結束時再釋放。並且支持拷貝構造和賦值運算符重載。

share_ptr模擬:

template<typename T>
class Shared_Ptr
{
public:
    Shared_Ptr(T* ptr)
        :_ptr(ptr)
        ,_count(new int(0))
    {
    }
    ~Shared_Ptr()
    {
        if(--(*_count)==0)
        {
            delete _ptr;
            delete _count;
            _ptr=_count=NULL;
        }
    }
    Shared_Ptr(Shared_Ptr<T> & a)
    {
            _ptr=a._ptr;
            _count=a._count;
            (*_count)++;
    }
    Shared_Ptr<T>& operator =(Shared_Ptr<T>& a)
    {
        if(&a!=this)
        {
            if(--(*_count)==0)
            {
                delete _ptr;
                delete _count;
                _ptr=_count=NULL;
            }
            _ptr=a._ptr;
            _count=a._count;
            (*_count)++;
        }
        return *this;
    }


    Shared_Ptr<T>& operator =(Shared_Ptr<T> a)
    {

        if(a!=&this)
        {
            swap(a._ptr,_ptr);
            swap(a._count,_count);
        }
        return *this;
    }   
    T* operator ->()
    {
        return _ptr;
    }
    T& operator *()
    {
        return *_ptr;
    }
protected:
    T* _ptr;
    int * _count;
};

在C++11中才加入了shared_ptr和unique_ptr,weak_ptr。

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