再论智能指针(下)

1. SharedPointer的设计要点

(1)使用类模板技术

(2)通过计数机制(ref)标记堆内存:

  • 堆内存被执向时,ref++
  • 堆内存被释放时,ref--
  • ref为零时释放所执向的堆内存

2. 计数机制原理剖析

3. SharedPointer类的声明

 1 template <typename T>
 2 class SharedPointer : public Pointer<T>
 3 {
 4 protected:
 5     int* m_refCount; //计数机制成员
 6 public:
 7     SharedPointer(T* p = NULL);
 8     SharedPointer(const SharedPointer<T>& obj);
 9     
10     SharedPointer<T>& operator=(const SharedPointer<T>& obj);
11     
12     void clear(); //将当前指针置为空
13     
14     //由于SharedPointer支持多个对象同时指向一片堆空间
15     //因此必须支持比较操作!
16     bool operator==(const SharedPointer<T>& obj);
17     bool operator!=(const SharedPointer<T>& obj);
18     
19     ~SharedPointer();
20 };

note:

代码中的计数变量是使用了一个指针指向的堆空间,这样做是由于:

智能指针指向的对象是在堆空间,为了保持计数变量智能指针指向的对象保持相同的生命周期,计数变量应该也是在堆空间中。

4. SharedPointer类的实现

SharedPointer.h

  1 #ifndef _SHAREDPOINTER_H_
  2 #define _SHAREDPOINTER_H_
  3 
  4 #include "Pointer.h"
  5 #include "exception.h"
  6 #include <cstdlib>
  7 
  8 namespace DataStructureLib 
  9 {
 10     template <typename T>
 11 
 12     class SharedPointer :public Pointer<T>
 13     {
 14     protected:
 15         int* m_ref;//计数机制成员
 16         
 17         void assign(const SharedPointer<T>& obj)
 18         {
 19             this->m_pointer=obj.m_pointer;
 20             this->m_ref=obj.m_ref;
 21 
 22             if ( obj.m_ref)
 23             {    
 24                 (*this->m_ref)++;
 25             }     
 26         } 
 27     public:
 28         SharedPointer(T* p=NULL):Pointer(NULL) //构造函数  显式调用父类的构造函数
 29         {
 30             if (p)
 31             {
 32                 this->m_ref=static_cast<int*>(malloc(sizeof(int)));
 33                 if (this->m_ref)
 34                 {
 35                     *(this->m_ref)=1;
 36                     this->m_pointer=p;
 37                     
 38                 }
 39                 else
 40                     THROW_EXCEPTION(NotEnoughMemoryException,"No memory to create SharedPointer object ... ");
 41             }
 42         }
 43 
 44         SharedPointer(const SharedPointer<T>& obj):Pointer(NULL)
 45         {
 46             assign(obj);
 47         }
 48 
 49       SharedPointer<T>& operator =(const SharedPointer<T>& obj)
 50       {
 51           if (this!=&obj)
 52           {
 53              clear();//如果当前的sharepointer指针已经指向 另外一片堆空间,应该先置空当前指针,不让它指向任何堆空间
 54              assign(obj);
 55           }
 56          
 57 
 58           return *this;
 59       }
 60 
 61       void clear()
 62       {//置空函数
 63           T* todel=this->m_pointer;
 64           int *ref=this->m_ref;
 65 
 66           this->m_pointer=NULL;
 67           this->m_ref=NULL;
 68 
 69           if ( ref)
 70           {
 71               (*ref)--;//释放一个指针减1
 72 
 73               if (*ref==0)//若堆空间没有对应的指针指向
 74               {
 75                   free(ref);
 76                   ref=NULL;
 77                  
 78                   delete todel;
 79               }
 80           }
 81       }
 82 
 83       ~SharedPointer()
 84       {
 85           clear();
 86       }
 87     };
 88     
 89     
 90     
 91     //由于SharedPointer支持多个对象同时指向一片堆空间。因此必须支持比较操作!
 92 
 93     template<typename T>
 94     bool operator == (const SharedPointer<T>& l,const SharedPointer<T>& obj)
 95     {
 96         return (l.get()==obj.get());
 97     }
 98 
 99     template<typename T>
100     bool operator !=(const SharedPointer<T>& l,const SharedPointer<T>& obj)
101     {
102         return !(l==obj);
103     }
104 
105 
106 
107 }
108 
109 #endif

测试代码:

 1 #include<iostream>
 2 #include "SharedPointer.h"
 3 using namespace std;
 4 using namespace DataStructureLib;
 5 
 6 class Test : public Object
 7 {
 8     
 9 public:
10     int m_value;
11     Test():m_value(0)
12     {
13         cout << "Test()" << endl;
14     }
15 
16     ~Test()
17     {
18         cout <<"~Test()" << endl;
19     }
20 };
21 int main(int argc, char const *argv[])
22 {
23     SharedPointer<Test> sp0 = new Test();
24     SharedPointer<Test> sp1 = sp0;
25     SharedPointer<Test> sp2 = NULL;
26 
27       sp2 = sp1;
28 
29       sp0->m_value=100;
30 
31       cout << sp0->m_value << endl;
32       cout << sp1->m_value << endl;
33       cout << sp2->m_value << endl;
34     //system("pause"); 
35     return 0;
36 }

结果

5.智能指针使用军规

(1)只能用来指向堆空间中的单个对象(变量)

(2)不同类型的智能指针对象不能混合使用

(3)不要使用delete释放智能指针指向的堆空间

6.小结

 (1)SharedPointer最大程度的模拟了原生指针的行为

 (2)计数机制确保多个智能指针合法的指向同一片堆空间

 (3)智能指针只能用于指向堆空间中的内存(不能是栈空间或者全局区的内存数据)

 (4)不同类型的智能指针(上一节和这一节的两种)不要混合使用

 (5)堆对象的生命周期由智能指针进行管理(申请和删除)

原文地址:https://www.cnblogs.com/zhaobinyouth/p/9769943.html