用c++简单实现智能指针(转)

http://blog.csdn.net/xinpo66/article/details/8786057

用c++简单实现智能指针

      什么是智能指针?答案相当简单;智能指针是聪明的普通指针。这是什么意思?实际上,智能指针是一些对象,表现出普通指针的功能但是比普通指针多做了一些事情。这些对象像普通指针一样灵活,并且管理对象有自己的优点(比如构造器和自动析构)。智能指针解决了普通指针的一些问题。

      普通指针的问题。

      我们使用C++语言中的指针,最常见的问题是什么?内存管理吧,请看下面的代码:

[cpp] view plaincopy
 
  1. char* pName  = new char[1024];  
  2. …  
  3. SetName(pName);  
  4. …  
  5. …  
  6. if(null != pName)  
  7. {  
  8.        delete[] pName;   
  9. }  
 
      好多次我们都会忘记释放pNme,并且管理释放这些不会再用到的指针将会是很大的工程。可不可以指针自身进行管理?当然,智能指针就可以做到。我们实现一个智能指针,看看智能指针如何处理的更好。
      下面写一个实际例子,先写一个叫做Person的类。
     
[cpp] view plaincopy
 
  1. class Person  
  2. {  
  3.     int age;  
  4.     char* pName;  
  5.   
  6.     public:  
  7.         Person(): pName(0),age(0)  
  8.         {  
  9.         }  
  10.         Person(char* pName, int age): pName(pName), age(age)  
  11.         {  
  12.         }  
  13.         ~Person()  
  14.         {  
  15.         }  
  16.   
  17.         void Display()  
  18.         {  
  19.             printf("Name = %s Age = %d \n", pName, age);  
  20.         }  
  21.         void Shout()  
  22.         {  
  23.             printf("Ooooooooooooooooo");  
  24.         }   
  25. };  

下面是客户端代码使用Person类。

[cpp] view plaincopy
 
  1. void main()  
  2. {  
  3.     Person* pPerson  = new Person("Scott", 25);  
  4.     pPerson->Display();  
  5.     delete pPerson;  
  6. }  
现在我们来看这段代码,每当我创建一个指针,都要管理释放它。我要自动的释放它,智能指针可以。因此我们创建一个SP类来管理Person的对象,客户端的代码可以这样写:

[cpp] view plaincopy
 
  1. void main()  
  2. {  
  3.     SP p(new Person("Scott", 25));  
  4.     p->Display();  
  5.     // Dont need to delete Person pointer..  
  6. }  

[cpp] view plaincopy
 
  1. void main()  
  2. {  
  3.     SP p(new Person("Scott", 25));  
  4.     p->Display();  
  5.     // Dont need to delete Person pointer..  
  6. }  

注意:
     1,我们创建了一个SP对象来管理Person的指针,当SP对象的作用域结束,会自动析构,它将释放Person的指针。
     2,我们可以使用SP的对象p调用Display()函数,就像Person类的对象指针调用Display()函数,它的行为表现的像Person类的对象指针。
智能指针接口
   智能指针表现出指针的行为,所以应该支持如下运算符:
 
  • Dereferencing (operator *)
  • Indirection (operator ->)
 
下面实现智能指针SP:
[cpp] view plaincopy
 
  1. class SP  
  2. {  
  3. private:  
  4.     Person*    pData; // pointer to person class  
  5. public:  
  6.     SP(Person* pValue) : pData(pValue)  
  7.     {  
  8.     }  
  9.     ~SP()  
  10.     {  
  11.         // pointer no longer requried  
  12.         delete pData;  
  13.     }  
  14.   
  15.     Person& operator* ()  
  16.     {  
  17.         return *pData;  
  18.     }  
  19.   
  20.     Person* operator-> ()  
  21.     {      
  22.         return pData;  
  23.     }  
  24. };  

这就是我们智能指针,当它的析构函数被调用时会释放Person类的对象指针。它也支持类似于指针的操作。
 
通用的智能指针
 
 
但是有个问题,我们智能控制Person类,也就是说每一种类型我们都要实现一个智能指针。我们可以使用模版使它通用。
 
[cpp] view plaincopy
 
  1. template < typename T > class SP  
  2. {  
  3.     private:  
  4.     T*    pData; // Generic pointer to be stored  
  5.     public:  
  6.     SP(T* pValue) : pData(pValue)  
  7.     {  
  8.     }  
  9.     ~SP()  
  10.     {  
  11.         delete pData;  
  12.     }  
  13.   
  14.     T& operator* ()  
  15.     {  
  16.         return *pData;  
  17.     }  
  18.   
  19.     T* operator-> ()  
  20.     {  
  21.         return pData;  
  22.     }  
  23. };  
  24.   
  25. void main()  
  26. {  
  27.     SP<Person> p(new Person("Scott", 25));  
  28.     p->Display();  
  29.     // Dont need to delete Person pointer..  
  30. }  

我们的智能指针这样就真的智能了吗?验证下面的代码:
[cpp] view plaincopy
 
  1. void main()  
  2. {  
  3.     SP<Person> p(new Person("Scott", 25));  
  4.     p->Display();  
  5.     {  
  6.         SP<Person> q = p;  
  7.         q->Display();  
  8.         // Destructor of Q will be called here..  
  9.     }  
  10.     p->Display();  
  11. }  

这样就会存在一个问题:p和q关联到了Person类的相同对象指针,当q结束它的作用域时会释放Person类的对象指针,我们用p调用Display()函数会因为垂悬指针而失败。我们应该在不使用它的时候再释放,智能指针中引入计数便可解决。
 
计数器。
下面实现一个计数器的类RC.
[cpp] view plaincopy
 
  1. class RC  
  2. {  
  3.     private:  
  4.     int count; // Reference count  
  5.   
  6.     public:  
  7.     void AddRef()  
  8.     {  
  9.         // Increment the reference count  
  10.         count++;  
  11.     }  
  12.   
  13.     int Release()  
  14.     {  
  15.         // Decrement the reference count and  
  16.         // return the reference count.  
  17.         return --count;  
  18.     }  
  19. };  

下面把计数器引入到我们的智能指针中:
[cpp] view plaincopy
 
  1. template < typename T > class SP  
  2. {  
  3. private:  
  4.     T*    pData;       // pointer  
  5.     RC* reference; // Reference count  
  6.   
  7. public:  
  8.     SP() : pData(0), reference(0)   
  9.     {  
  10.         // Create a new reference   
  11.         reference = new RC();  
  12.         // Increment the reference count  
  13.         reference->AddRef();  
  14.     }  
  15.   
  16.     SP(T* pValue) : pData(pValue), reference(0)  
  17.     {  
  18.         // Create a new reference   
  19.         reference = new RC();  
  20.         // Increment the reference count  
  21.         reference->AddRef();  
  22.     }  
  23.   
  24.     SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)  
  25.     {  
  26.         // Copy constructor  
  27.         // Copy the data and reference pointer  
  28.         // and increment the reference count  
  29.         reference->AddRef();  
  30.     }  
  31.   
  32.     ~SP()  
  33.     {  
  34.         // Destructor  
  35.         // Decrement the reference count  
  36.         // if reference become zero delete the data  
  37.         if(reference->Release() == 0)  
  38.         {  
  39.             delete pData;  
  40.             delete reference;  
  41.         }  
  42.     }  
  43.   
  44.     T& operator* ()  
  45.     {  
  46.         return *pData;  
  47.     }  
  48.   
  49.     T* operator-> ()  
  50.     {  
  51.         return pData;  
  52.     }  
  53.       
  54.     SP<T>& operator = (const SP<T>& sp)  
  55.     {  
  56.         // Assignment operator  
  57.         if (this != &sp) // Avoid self assignment  
  58.         {  
  59.             // Decrement the old reference count  
  60.             // if reference become zero delete the old data  
  61.             if(reference->Release() == 0)  
  62.             {  
  63.                 delete pData;  
  64.                 delete reference;  
  65.             }  
  66.   
  67.             // Copy the data and reference pointer  
  68.             // and increment the reference count  
  69.             pData = sp.pData;  
  70.             reference = sp.reference;  
  71.             reference->AddRef();  
  72.         }  
  73.         return *this;  
  74.     }  
  75. };  

在看看客户端的代码:
[cpp] view plaincopy
 
  1. Collapse | Copy Code  
  2. void main()  
  3. {  
  4.     SP<PERSON> p(new Person("Scott", 25));  
  5.     p->Display();  
  6.     {  
  7.         SP<PERSON> q = p;  
  8.         q->Display();  
  9.         // Destructor of q will be called here..  
  10.   
  11.         SP<PERSON> r;  
  12.         r = p;  
  13.         r->Display();  
  14.         // Destructor of r will be called here..  
  15.     }  
  16.     p->Display();  
  17.     // Destructor of p will be called here   
  18.     // and person pointer will be deleted  
  19. }  

 

原文地址:https://www.cnblogs.com/wainiwann/p/3066275.html