智能指针发展

智能指针就是智能/自动化的管理指针所指向的动态资源的释放。并且可以向指针一样使用。

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。

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