浅谈c++智能指针

所谓的智能指针就是智能/自动化的管理指针所指向的动态资源的释放。
智能指针的产生是由于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;
};

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值