浅谈c++智能指针

来源:互联网 发布:伴奏制作软件 编辑:程序博客网 时间:2024/06/05 02:06

所谓的智能指针就是智能/自动化的管理指针所指向的动态资源的释放。
智能指针的产生是由于C++没有内存的自动回收机制,每次new出来的空间都需要收到的delete,而在个别情况下,总是无法及时的delete,或者异常导致程序提早退出,造成内存泄漏。于是弥补上述不足的智能指针应用而生。
智能指针的发展可分为三个阶段
(1)auto_ptr c++98
(2)scoped_ptr/shared_ptr/weak_ptr boost库
(3)unique_ptr/shared_ptr/weak_ptr c++11

设计思想

auto_ptr实际上是管理权限的转移,此设计本身带有缺陷,不宜使用。

template<class T>    class Auto_ptr    {    public:    Auto_ptr(T* ptr)    :_ptr(ptr)    {}    Auto_ptr(Auto_ptr<T>& ap)    {    ap._ptr = NULL;    }    Auto_ptr<T>& operator=(Auto_ptr<T>& ap)    {    if(_ptr != ap._ptr)    {     delete _ptr;     _ptr = NULL;     _ptr = ap._ptr;     ap._ptr = NULL;    }    return *this;    }    ~Auto_ptr()    {    if(_ptr)    {    delete _ptr;    }    }    T* operator->()    {    return _ptr;    }    T& operator*()    {    return *_ptr;    }    private:    T* _ptr;    };

通过管理权的转移,避免了同一块空间被释放两次,的问题,但同时,原有指针也失去了对该空间的操作权限,所以不建议使用该方法。

scoped_ptr又叫 守卫指针,用来防止拷贝,可以解决Auto_ptr的问题。
解决的方法:
(1)拷贝构造和赋值运算符的操作可以只声明,不定义。
(2)将声明为私有,防止定义。

template<class T>class Scoped_ptr{public:Scoped_ptr(T* ptr)        :_ptr(ptr)        {} ~Scoped_ptr() { if(_ptr) { delete _ptr; } }        T* operator->() { return _ptr; } T& operator*() { return *_ptr; }private:Scoped_ptr<T>& operator=(Scoped_ptr<T>& sp);Scoped_ptr(Scoped_ptr<T>& sp); private:T* _ptr;};指针功能明显受到限制,后来人们就不用了;于是行的智能指针诞生了。

shared_ptr采用了引用计数的思想,为需要拷贝和福祉的指针开启另一个空间。

temeplate<class T>class Shared_ptr{public:Shared_ptr(T* ptr)         :_ptr(ptr)         ,_ref(new int(1))         {}Shared_ptr(Shared_ptr<T>& sp)               :_ptr(sp.ptr)               ,_ref(sp.ref){  (*_ref)++;}         Shared_ptr<T>& operator=(Shared_ptr<T>& sp){if(_ptr != sp._ptr){if(--(*_ref) == 0){delete _ptr;deelte _ref;} delete _ptr; _ptr = sp._ptr; _ref = sp._ref; (*_ref)++;}return *this;}~Shared_ptr(){if(--(*_ref)==0){delete _ptr;delete _ref;}}T* operator->(){return _ptr;}T& operator*(){return _*ptr;}int Getref(){return *_ref} T* Getptr(){return _ptr;}protected:T* _ptr;int* _ref;};

上面的代码虽然简单的实现引用计数版的简化版智能指针Shared_ptr;但是存在着一下问题,
(1)引用计数更新存在着线程安全。
(2)循环引用的问题。
(3)定制删除器。

解决循环引用的问题,需要一个弱指针。

   struct ListNode{    //WeakPtr<ListNode> _prev;    //WeakPtr<ListNode> _next;    SharedPtr<ListNode> _prev;    SharedPtr<ListNode> _next;    ~ListNode()    {        cout << "~ListNode()" << endl;    }};void TestCycleRef(){    SharedPtr<ListNode> cur = new ListNode;    SharedPtr<ListNode> next = new ListNode;    cout << "cur->Coun t:" << cur.RefCount() << endl;    cout << "next->Coun t:" << next.RefCount() << endl;    cur->_next = next;    next->_prev = cur;    cout << "cur->Coun t:" << cur.RefCount() << endl;    cout << "next->Coun t:" << next.RefCount() << endl;}

cur与next的引用计数均为2,且均无法释放,改为weak_ptr,(不增加引用计数)

template<class T>class WeakPtr{public:    WeakPtr()        :_ptr(NULL)    {}    WeakPtr(const SharedPtr<T>& sp)        :_ptr(sp.GetPtr())    {}    T& operator*()    {        return *_ptr;    }    T* operator->()    {        return _ptr;    }protected:    T* _ptr;};

如此解决了循环引用的问题

原创粉丝点击