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)堆对象的生命周期由智能指针进行管理(申请和删除)