我们知道c++标准库中定义了智能指针auto_ptr,但是我们很少用它,因为虽然它能够自动回收动态开辟的内存,不需要程序员自己去维护动态开辟的内存,但是当用它去赋值或者是拷贝构造时有一个管理权转移的过程,这样我们就不能很方便的使用auto_ptr。

下面是简单的auto_ptr的实现,我们可以看到在复制和赋值时它将转移管理权

template<class T>

class AutoPtr

{

public:

     AutoPtr(T* ptr)

      :_ptr(ptr)

     {}

     ~AutoPtr()

     {

          if (_ptr)

          {

               delete _ptr;

          }

     }

     AutoPtr(AutoPtr<T>& ap)

      :_ptr(ap._ptr)

     {

          ap._ptr = NULL;//管理权转移,原来ap的_ptr置空

     }

     AutoPtr<T>& operator=(AutoPtr<T>& ap)

     {

              if (this != &ap)

          {

               delete _ptr;

               _ptr = ap._ptr;

               ap._ptr = NULL;//管理权转移,原来ap的_ptr置空


          }

      return *this;

     }

     T& operator*()

     {

          return *_ptr;

     }

     T* operator->()

     {

          return _ptr;

     }

private:

     T* _ptr;

};

我们知道,boost库中也有智能指针,它们的实现方式与c++标准库中的不同。

scoped_ptr,scoped_Array是用很简单粗暴(防拷贝)地方式实现的智能指针,它不允许用户对该对象进行复制和赋值。下面是它们的实现方式:

template<typename T>
class ScopedPtr
{
public:
     ScopedPtr(T* ptr)
     :_ptr(ptr)
     {}
     ~ScopedPtr()
     {
          if (_ptr)
          {
               delete _ptr;
          }
     }
     T* operator->()
     {
          return _ptr;
     }
     T& operator*()
     {
          return *_ptr;
     }
protected:
     ScopedPtr(ScopedPtr<T>& sp);//只声明不实现,并且声明为私有,防止其他人实现并调用
     ScopedPtr<T>& operator=(ScopedPtr<T>& sp);//只声明不实现,并且声明为私有,防止其他人实现并调用 

private:
     T* _ptr;
};
 
template<class T>
class ScopedArray
{
public:
     ScopedArray(T* ptr)
      :_ptr(ptr)
     {}
     ~ScopedArray()
     {
          if (_ptr)
          {
               cout << "delete" << endl;
               delete[] _ptr;
          }
     }
     T& operator[](int index)
     {
          return _ptr[index];
     }
protected:
     ScopedArray(ScopedArray<T>& sparr);
     ScopedArray& operator=(ScopedArray<T>& sparr);
private:
     T* _ptr;
};

boost库中的shared_ptr,shared_Array是用一个指针和一个引用计数来管理动态开辟的内存,在动态开辟一块空间的同时开辟一块可以存储引用计数的大小的空间进行引用计数,记录这块空间被引用的次数。

与auto_ptr不同,可允许多个指针管理统一空空间。

template<class T>
class SharedPtr
{
public:
     SharedPtr(T* ptr)
      :_ptr(ptr)
      , _pCount(new long(1))
     {}
     SharedPtr(const SharedPtr<T>& sp)
      :_ptr(sp._ptr)
      , _pCount(sp._pCount)
     {
          ++(*_pCount);
     }
     /*SharedPtr& operator=(const SharedPtr<T>& sp)//传统的赋值方法
     {
         if (_ptr != sp._ptr)
         {
             Release();
             _ptr = sp._ptr;
             _pCount = sp._pCount;
             ++(*_pCount);
         }
         return *this;
     }*/
     SharedPtr& operator=(SharedPtr<T> sp)//现代的赋值方法
     {
          swap(_ptr, sp._ptr);
          swap(_pCount, sp._pCount);
          return *this;
     }
     ~SharedPtr()
     {
          Release();
     }
     long UseCount()
     {
          return *_pCount;
     }
     T* operator->()
     {
          return _ptr;
     }
     T& operator*()
     {
          return *_ptr;
     }
protected:
     void Release()
     {
      if (--(*_pCount) == 0)
      {
       delete _ptr;
       delete _pCount;
      }
     }
private:
     T* _ptr;
     long* _pCount;//引用计数器
};
 
 
template<class T>
class SharedArray
{
public:
     SharedArray(T* ptr)
      :_ptr(ptr)
      , _pCount(new long(1))
     {}
     ~SharedArray()
     {
      Release();
     }
     SharedArray(const SharedArray<T>& spArr)
      :_ptr(spArr._ptr)
      ,_pCount(spArr._pCount)
     {
      ++(*_pCount);
     }
     /*SharedArray& operator=(SharedArray<T> spArr)
     {
      swap(_ptr, spArr._ptr);
      swap(_pCount, spArr._pCount);
     }*/
     SharedArray& operator=(const SharedArray<T>& spArr)
     {
      if (_ptr != spArr._ptr)
      {
           Release();
           _ptr = spArr._ptr;
           _pCount = spArr._pCount;
           ++(*_pCount);
      }
      return *this;
     }
     T& operator[](int index)
     {
          return _ptr[index];
     }
private:
     void Release()
     {
          if (--(*_pCount) == 0)
          {
               delete[] _ptr;
               delete _pCount;
          }
     }
private:
     T* _ptr;
     long* _pCount;
};