C++智能指针

在C++中,动态内存的管理是用一对运算符完成的:new和delete,new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。
动态内存管理经常会出现两种问题:一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。
因此为了更加容易和安全的使用动态内存,引入了智能指针的概念
智能指针的行为类似常规指针,重要的区别是他负责自动释放所指向的对象。
智能指针共分为4种,即boost库中的auto_ptr、scoped_ptr、shared_ptr、weak_ptr。

auto_ptr


//正确情况:
int i=new int(1);   //堆上的空间——动态开辟
auto_ptr<int> ap1(&i);
//错误情况:
int i=1;  //栈上的空间
auot_ptr<int> ap2(&i);

缺陷

  1. 不要使用auto_ptr保存一个非动态开辟空间的指针,因为在作用域结束的时候,会执行智能指针的析构函数,释放这块空间,但非动态的空间又无法释放;
  2. 不要使用两个auto_ptr指针指向同一个指针,具体原因上面解释过;
  3. 不要使用auto_ptr指向一个指针数组,因为auto_ptr的析构函数所用的是delete而不是delete[],不匹配;
  4. 不要将auto_ptr储存在容器中,因为赋值和拷贝构造后原指针无法使用。

还有最重要的一点就是,什么情况下也别使用auto_ptr智能指针。

scoped_ptr



template<typename T>
class ScopedPtr
{
public:
    explicit ScopedPtr(T *p=0):mp(p)
    {
    }
    ~ScopedPtr()
    {
        delete mp;
    }
    void reset(T *p=0)
    {
        if(mp!=p)
        {
            delete mp;
            mp=p;
        }
    }
    T &operator*() const
    {
        if(mp!=0)
            return *mp;
        else
            throw std::runtime_error("the pointer is null");
    }
    T *operator->() const
    {
        if(mp!=0)
            return mp;
        else
            throw std::runtime_error("the pointer is null");
    }
    T *get() const
    {
        return mp;
    }
    void swap(ScopedPtr &rhs)
    {
        T *temp=mp;
        mp=rhs.mp;
        rhs.mp=temp;
    }
private:
    ScopedPtr(const ScopedPtr& rhs);
    ScopedPtr &operator=(const ScopedPtr& rhs);
    T *mp;
};

可以看见最大的不同就是scoped_ptr没有给出拷贝构造和赋值运算符的重载运算符的定义,只给了private下的声明,即表明scoped_ptr智能指针无法使用一个对象创建另一个对象,也无法采用赋值的形式。这无疑提升了智能指针的安全性,但是又存在无法“++”、“–”这些操作,当然也多了“*”、“->”这两种操作。所以这种形式叶并不是最完美的。所以又有了shared_ptr

shared_ptr

template<class T>  
class my_shared_ptr{  
public:  
    my_shared_ptr(T* pt){  
        _pBlock = new ControlBlock(pt);  
    }  
    my_shared_ptr(const my_shared_ptr& rhs){  
        _pBlock = rhs._pBlock;  
        _pBlock->ref_count++;  
    }  
    ~my_shared_ptr(){  
        _pBlock->ref_count --;  
        if(0 == _pBlock->ref_count)  
            delete _pBlock;  
    }  
    my_shared_ptr& operator=(const my_shared_ptr& rhs){  
        if(this == &rhs)  
            return *this;  

        _pBlock->ref_count --;  
        if(0 == _pBlock->ref_count)  
            delete _pBlock;  

        _pBlock = rhs._pBlock;  
        _pBlock->ref_count++;  
    }  

    T* get(){return _pBlock->_ptr;}  
    T* operator->(){return _pBlock->_ptr;}  
    void reset(T* pt){  
        _pBlock->ref_count --;  
        if(0 == _pBlock->ref_count)  
            delete _pBlock;  

        _pBlock = new ControlBlock(pt);  
    }  

private:  
    struct ControlBlock{  
        int ref_count;  
        T* _ptr;  
        ControlBlock(T* pt){  
            _ptr = pt;  
            ref_count = 1;  
        }  
        ~ControlBlock(){  
            delete _ptr;  
        }  
    };  
    ControlBlock* _pBlock;  
};  

shared_ptr和以上二者的最大区别就是他维护了一个引用计数,用于检测当前对象所管理的指针是否还被其他智能指针使用(必须是shared_ptr管理的智能指针),在析构函数时对其引用计数减一,判断是否为0,若为0,则释放这个指针和这个引用计数的空间。其实,这个原理就和string类的浅拷贝是一样的。

weak_ptr


pragma once #include <memory>

  #define _MT_INCR(mtx, x)     _InterlockedIncrement(&x)
  #define _MT_DECR(mtx, x)     _InterlockedDecrement(&x)
  #define _MT_CMPX(x, y, z)    _InterlockedCompareExchange(&x, y, z)
class RefCountBase
{
private:
      virtual void _Destroy() = 0;
      virtual void _DeleteThis() = 0;
      long _Uses;
      long _Weaks;
protected:
      RefCountBase()
            : _Uses(1)
            , _Weaks(1)
      {}
public:
      virtual ~RefCountBase()
      {}
      // 如果usecount不为0时,增加usecount的引用计数,成功返回true
      bool _Incref_nz()
      {
            // 循环知道增加成功
            for (; ; )
            {     // loop until state is known
                  long _Count = (volatile long&)_Uses;
                  if (_Count == 0)
                        return (false);
                  if (_MT_CMPX(_Uses, _Count + 1, _Count) == _Count)
                        return (true);
            }
      }
      // 增加usecount
      void _Incref()
      {
            _MT_INCR(_Mtx, _Uses);
      }
      // 增加weakcount引用计数
      void _Incwref()
      {
            _MT_INCR(_Mtx, _Weaks);
      }
      // 减少usecount引用计数
      void _Decref()
      {     // 减少usecount引用计数,如果usecount减后为0,释放资源
            if (_MT_DECR(_Mtx, _Uses) == 0)
            {
                  //释放管理的资源,减少weakcount引用计数
                  _Destroy();
                  _Decwref();
            }
      }
      // 减少weakcount的引用计数
      void _Decwref()
      {
            if (_MT_DECR(_Mtx, _Weaks) == 0)
                  _DeleteThis();
      }
      // 获取usecount
      long _Use_count()const
      {
            return (_Uses);
      }
      bool _Expired() const
      {
            return (_Uses == 0);
      }
      virtual void *_Get_deleter(const _XSTD2 type_info&) const
      {
            return (0);
      }
};
template<class T>
class RefCount: public RefCountBase
{
public:
      RefCount(T* p)
            : RefCountBase()
            , _p(p)
      {}
private:
      // 释放管理的资源
      virtual void _Destroy()
      {
            delete _p;
      }
      // 释放自身
      virtual void _DeleteThis()
      {
            delete this;
      }
      T * _p;
};
template<class T,class Del>
class RefCountDel: public RefCountBase
{
public:
      RefCountDel(T *p, Del Dtor)
            : RefCountBase()
            , _p(p)
            , _Dtor(Dtor)
      {}
      virtual void *_Get_deleter(const _XSTD2 type_info& _Type) const
      {     // return address of deleter object
            return ((void *)(_Type == typeid(Del) ? &_Dtor : 0));
      }
private:
      // 释放管理的资源
      virtual void _Destroy()
      {
            _Dtor(_p);
      }
      virtual void _DeleteThis()
      {
            delete this;
      }
      T * _p;
      Del _Dtor;
};
//定制空间配置器
template<class T,class Del,class Alloc>
class RefCountDelAlloc: public RefCountBase
{
public:
      typedef RefCountDelAlloc<T, Del, Alloc> _Myty;
      typedef typename Alloc::template rebind<_Myty>::other _Myalty;
      RefCountDelAlloc(T* p, Del Dtor, _Myalty _Al)
            : RefCountBase()
            , _p(p)
            , _Dtor(Dtor)
            , _Myal(_Al)
      {}
      virtual void *_Get_deleter(const _XSTD2 type_info& _Type) const
      {
            return ((void *)(_Type == typeid(Del) ? &_Dtor : 0));
      }
private:
      // 释放管理的资源
      virtual void _Destroy()
      {
            _Dtor(_p);
      }
      // 释放自身
      virtual void _DeleteThis()
      {     // destroy self
            _Myalty _Al = _Myal;
            _Dest_val(_Al, this);
            _Al.deallocate(this, 1);
      }
      T * _p;
      Del _Dtor;  // the stored destructor for the controlled object
      _Myalty _Myal;    // the stored allocator for this
};
// DECLARATIONS
template<class T>
class WeakPtr;
template<class T>
class SharedPtr;
// SharedPtr和WeakPtr的基类
template<class T>
class PtrBase
{
public:
      typedef PtrBase<T> _Myt;
      typedef T Elem;
      typedef Elem ElementType;
      PtrBase()
            : _ptr(0)
            , _pRef(0)
      {}
      PtrBase(_Myt&& _Right)
            : _ptr(0)
            , _pRef(0)
      {
            _Assign_rv(_STD forward<_Myt>(_Right));
      }
      // construct _Ptr_base object that takes resource from _Right
      _Myt& operator=(_Myt&& _Right)
      {     
            _Assign_rv(_STD forward<_Myt>(_Right));
            return (*this);
      }
      // assign by moving _Right
      void _Assign_rv(_Myt&& _Right)
      {
            if (this != &_Right)
                  _Swap(_Right);
      }
      // 获取引用计数
      long UseCount() const
      {     // return use count
            return (_pRef ? _pRef->_Use_count() : 0);
      }
      void _Swap(PtrBase& _Right)
      {
            std::swap(_pRef, _Right._pRef);
            std::swap(_ptr, _Right._ptr);
      }
      void* GetDeleter(const _XSTD2 type_info& _Type) const
      {     
            return (_pRef ? _pRef->_Get_deleter(_Type) : 0);
      }
      T* _Get() const
      {
            return (_ptr);
      }
      bool Expired() const
      {
            return (!_pRef || _pRef->_Expired());
      }
      // 增加引用计数usecount
      void _Decref()
      {
            if (_pRef != 0)
                  _pRef->_Decref();
      }
      void _Reset()
      {
            _Reset(0, 0);
      }
      template<class Ty>
      void _Reset(const PtrBase<Ty>& pb)
      {
            _Reset(pb._ptr, pb._pRef);
      }
      template<class Ty>
      void _Reset(Ty *Ptr, const PtrBase<Ty>& pb)
      {
            _Reset(Ptr, pb._pRef);
      }
      void _Reset(T* ptr, RefCountBase* pRef)
      {
            if (pRef)
                  pRef->_Incref();
            _Reset0(ptr, pRef);
      }
      void _Reset0(T* ptr, RefCountBase *pRef)
      {
            if (_pRef != 0)
                  _pRef->_Decref();
            _pRef = pRef;
            _ptr = ptr;
      }
      void _Decwref()
      {
            if (_pRef != 0)
                  _pRef->_Decwref();
      }
      void _Resetw()
      {
            _Resetw((_Elem *)0, 0);
      }
      template<class Ty>
      void _Resetw(const PtrBase<Ty>& pb)
      {
            _Resetw(pb._ptr, pb._pRef);
      }
      template<class Ty>
      void _Resetw(const Ty* ptr, RefCountBase* pRef)
      {
            _Resetw(const_cast<Ty*>(ptr), pRef);
      }
      template<class Ty>
      void _Resetw(Ty* ptr, RefCountBase* pRef)
      {
            if (pRef)
                  pRef->_Incwref();
            if (_pRef != 0)
                  _pRef->_Decwref();
            _pRef = pRef;
            _ptr = ptr;
      }
private:
      T *_ptr;
      RefCountBase *_pRef;
};
template<class T>
class SharedPtr: public PtrBase<T>
{
public:
      typedef SharedPtr<T> _Myt;
      typedef PtrBase<T> _Mybase;
      SharedPtr()
      {}
      explicit SharedPtr(T* p)
      {
            _Resetp(p);
      }
      // 带有删除器的构造函数
      template<class U,class Del>
      SharedPtr(U *p, Del Dt)
      {
            _Resetp(p, Dt);
      }
      // 带有空间配置器的构造函数
      template<class U,class D,class Alloc>
      SharedPtr(U *p, D Dt, Alloc Ax)
      {
            _Resetp(p, Dt, Ax);
      }
      SharedPtr(const _Myt& _Other)
      {
            this->_Reset(_Other);
      }
      template<class Ty>
      explicit SharedPtr(const WeakPtr<Ty>& _Other,bool _Throw = true)
      {
            this->_Reset(_Other, _Throw);
      }
      template<class Ty>
      explicit SharedPtr(const WeakPtr<Ty>& _Other)
      {
            this->_Reset(_Other, _Throw);
      }
      ~SharedPtr()
      {
            this->_Decref();
      }
      _Myt& operator=(const _Myt& _Right)
      {
            SharedPtr(_Right).Swap(*this);
            return (*this);
      }
      void Reset()
      {
            SharedPtr().swap(*this);
      }
      template<class U>
      void Reset(U* p)
      {
            SharedPtr(p).swap(*this);
      }
      template<class U,class Del>
      void Reset(U* p, Del Dt)
      {
            SharedPtr(p, Dt).swap(*this);
      }
      template<class U,class D,class _Alloc>
      void Reset(U *P, D Del, _Alloc _Ax)
      {
            SharedPtr(P, Del, _Ax).swap(*this);
      }
      void Swap(_Myt& sp)
      {
            this->_Swap(sp);
      }
      T* Get() const
      {
            return (this->_Get());
      }
      T& operator*() const
      {
            return (*this->_Get());
      }
      T* operator->() const
      {
            return (this->_Get());
      }
      bool Unique() const
      {
            return (this->use_count() == 1);
      }
private:
      template<class U>
      void _Resetp(U* p)
      {
            _Resetp0(p, new RefCount<U>(p));
      }
      template<class U,class D>
      void _Resetp(U *p, D Del)
      {
            _Resetp0(p, new RefCountDel<U, D>(p, Del));
      }
public:
      template<class U>
      void _Resetp0(U* p, RefCountBase* pRef)
      {
            this->_Reset0(p, pRef);
      }
};
template<class T>
void Swap(SharedPtr<T>& _Left,SharedPtr<T>& _Right)
{
      _Left.swap(_Right);
}
template<class D,class T>
D* GetDeleter(const SharedPtr<T>& _Sx)
{
      return ((D *)_Sx._Get_deleter(typeid(D)));
}
template<class T>
class WeakPtr: public PtrBase<T>
{
public:
      WeakPtr()
      {}
      WeakPtr(const WeakPtr& wp)
      {
            this->_Resetw(wp);
      }
      ~WeakPtr()
      {
            this->_Decwref();
      }
      WeakPtr& operator=(const WeakPtr& wp)
      {
            this->_Resetw(wp);
            return (*this);
      }
      WeakPtr& operator=(SharedPtr<T>& sp)
      {
            this->_Resetw(sp);
            return (*this);
      }
      void Reset()
      {
            this->_Resetw();
      }
      void Swap(WeakPtr& _Other)
      {
            this->_Swap(_Other);
      }
      bool Expired() const
      {
            return (this->_Expired());
      }
};


weak_ptr也维护了一个引用计数,跟shared_ptr维护的引用计数或互不干扰,或相互协同。weak_ptr的指针会在weak_ptr维护的引用计数上加一,而shared_ptr会在shared_ptr维护的引用计数上加一,这样在循环引用时,就会因为对不同引用的判断的不同,使最终决定是否释放空间的结果也不相同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值