模擬實現c++標準庫和boost庫中的智能指針

我們知道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;
};

 

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