智能指針的原理和簡單實現

  1. 什麼是智能指針?

    智能指針實質上是一個類,定義一個類來封裝資源的分配和釋放。這個類的構造函數中傳入一個指針,完成資源的分配和初始化。在析構函數中釋放傳入的該指針,完成資源的釋放。

  2. 爲什麼要用智能指針?

    智能指針就是智能,自動化的管理指針所指向的動態資源。

    例如以下情況:代碼中經常會忘記釋放動態開闢的內存資源,導致內存泄露。

// case1
void Test2()
{
 int* p1 = new int(2);
 bool isEnd = true;
 //...
 if (isEnd)
 {
  delete p1;
  return;
 }
 //...
 delete p1;
}
// case2
void DoSomeThing()
{
 //...
 throw 2;
 //...
}
void Test2()
{
 int* p1 = new int(2);
 //...
 try {
  DoSomeThing();
 }
 catch (...)
 {
  delete p1;
  throw;
 }
 //...
 delete p1;
}

  • 智能指針的簡單實現。

    Auto_ptr:不能共享所有權,只要出現兩個指針指向同一塊資源,就釋放前一個指針的管理權。保證只有一個指針指向一塊資源。

    Scoped_ptr:將類中的成員函數拷貝構造和賦值運算符只申明爲protected,不定義。所以不可能有兩個指針指向同一個對象。

    Shared_ptr:採用引用計數的方法。將一個計數器與類指向的對象相關聯,引用計數跟蹤共有多少個類對象共享同一指針。

    ScopedArray和Scoped_ptr類似,只是操作的是數組。SharedArray同理。

     

template <class T>
class AutoPtr
{
public:
 AutoPtr(T*ptr)
  :_ptr(ptr)
 {}
 AutoPtr( AutoPtr<T>&ap)
  :_ptr(ap._ptr)
 {
  ap._ptr = NULL;
 }
 AutoPtr<T>&operator=(const AutoPtr<T>&ap)
 {
  if (this != &ap)
  {
   delete _ptr;
   _ptr = ap._ptr;
   ap._ptr = NULL;
  }
 }
 ~AutoPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 T*_ptr;
};
struct Node
{
 int _data;
 Node*_next;
};
void Test_AutoPtr()
{
 int*p1 = new int(2);
 int*p2 = p1;
 int*p3 = p2;
 *p3 = 10;
 delete p1;
 AutoPtr<int>ap1(new int(2));
 AutoPtr<int>ap2=ap1;     //此時ap1爲NULL,無管理權
 AutoPtr<int>ap3(ap2);
                         //此時ap2爲NULL,無管理權
 //*ap2 = 10;            //程序崩潰    
 *ap3 = 10;
 AutoPtr<Node>sp1(new Node);
 sp1->_data = 10;
}
template<class T>
class ScopedPtr
{
public:
 ScopedPtr(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:                    //只申明,不定義,防止拷貝構造和賦值運算符重載。
 ScopedPtr(const ScopedPtr<T>&sp);   //保護,防止在外定義。若寫爲public,則有可能在類外定義。
 ScopedPtr<T>& operator=(const ScopedPtr<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedPtr()
{
 ScopedPtr<int>sp1(new int(3));
 //ScopedPtr<int>sp2(sp1);             //protectd:無法訪問
}
template <class T>
class ScopedArray
{
public:
 ScopedArray(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedArray()
 {
  if (_ptr)
  {
   delete[]_ptr;
  }
 }
 T&operator[](size_t Index)
 {
  return _ptr[Index];
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 ScopedArray(const ScopedArray<T>&sp);
 ScopedArray<T>&operator=(const ScopedArray<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedArray()
{
 ScopedArray<int>sp1(new int[5]);
 //ScopedPtr<int>sp2(sp1);
 
}
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<T>&operator=(const SharedPtr<T>&sp)    //傳統寫法
 //{
 // if (this != &sp)
 // {
 //  if (--(*_Pcount) == 0)
 //  {
 //   delete _ptr;
 //   delete _Pcount;
 //  }
 //  _ptr = sp._ptr;
 //  _Pcount = sp._Pcount;
 //  ++(*_Pcount);
 // }
 // return *this;
 //}
 SharedPtr<T>&operator=(const SharedPtr<T>sp)     //現代寫法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedPtr()
 {
  if (--(*_Pcount) == 0)
  {
   delete _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedPtr()
{
 SharedPtr<int>sp1(new int(2));
 SharedPtr<int>sp2(sp1);
}
template <class T>
class SharedArray
{
public:
 SharedArray(T*ptr)
  :_ptr(ptr)
  , _Pcount(new long (1))
 {}
 SharedArray(const SharedArray<T>&sp)
  :_ptr(sp._ptr)
  , _Pcount(sp._Pcount)
 {
  ++*(_Pcount);
 }
 SharedArray<T>&operator=(const SharedArray<T>sp)     //現代寫法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedArray()
 {
  if (--(*_Pcount) == 0)
  {
   delete[] _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 T&operator[](size_t Index)
 {
     return _ptr[Index];
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedArray()
{
 SharedArray<int>sp1(new int[5]);
 SharedArray<int>sp2(sp1);
}

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