std::shared_ptr
是經過指針保持對象共享全部權的智能指針。多個 shared_ptr
對象可佔有同一對象大概實現了一下,主要實現原理爲,共享指針內部持有堆資源的指針以及引用計數的指針,經過對這兩個指針的維護,達到多個共享對象對同一資源的控制ios
實現主要分爲三個文件。share_ptr.h,smart_ptr_define.h, main.cpp (編譯平臺:Linux centos 7.0 編譯器:gcc 4.8.5 )centos
1 //smart_ptr_define.h 2 #ifndef __SMART_PTR_DEFINE_H__ 3 #define __SMART_PTR_DEFINE_H__ 4 5 #include <assert.h> 6 7 #define PTR_ASSERT(x) assert(x) 8 9 #define _SMART_PTR_BEGIN namespace smartptr { 10 #define _SMART_PTR_END } 11 #define _SMART_PTR ::smartptr:: 12 13 #endif
主要實現文件share_ptr.h網絡
1 #ifndef __SHARE_PTR_H__ 2 #define __SHARE_PTR_H__ 3 4 #include <iostream> 5 #include "smart_ptr_define.h" 6 7 _SMART_PTR_BEGIN 8 9 template <class T> 10 struct default_deleter 11 { 12 void operator()(T* ptr) 13 { 14 if (ptr != NULL) 15 { 16 delete ptr; 17 ptr = NULL; 18 } 19 } 20 }; 21 22 template <class T, class deleter = default_deleter<T> > 23 class shared_ptr 24 { 25 public: 26 typedef shared_ptr<T, deleter> SHARE_PTR; 27 28 shared_ptr() 29 { 30 m_ptr = NULL; 31 m_iRefCount = NULL; 32 } 33 34 explicit shared_ptr(T* ptr) 35 { 36 if (ptr != NULL) 37 { 38 m_ptr = ptr; 39 RefCountInit(); 40 } 41 } 42 43 shared_ptr(deleter d, T* ptr) 44 { 45 if (ptr != NULL) 46 { 47 m_ptr = ptr; 48 m_deleter = d; 49 RefCountInit(); 50 } 51 } 52 53 //拷貝構造 54 shared_ptr(const SHARE_PTR& sh_ptr) 55 { 56 if (sh_ptr.m_ptr != NULL) 57 { 58 m_ptr = sh_ptr.m_ptr; 59 m_deleter = sh_ptr.m_deleter; 60 m_iRefCount = sh_ptr.m_iRefCount; 61 62 RefCountIncrease(); 63 } 64 } 65 66 //賦值運算符 67 SHARE_PTR& operator = (const SHARE_PTR& sh_ptr) 68 { 69 if (this != &sh_ptr) 70 { 71 RefCountDecrease(); 72 73 if (sh_ptr.m_ptr != NULL) 74 { 75 m_ptr = sh_ptr.m_ptr; 76 m_deleter = sh_ptr.m_deleter; 77 m_iRefCount = sh_ptr.m_iRefCount; 78 79 RefCountIncrease(); 80 } 81 } 82 83 return (*this); 84 } 85 86 ~shared_ptr() 87 { 88 RefCountDecrease(); 89 } 90 91 public: 92 //提領操做 93 T& operator*() 94 { 95 PTR_ASSERT(m_ptr != NULL); 96 return *(m_ptr); 97 } 98 99 //原始指針操做 100 T* operator->() 101 { 102 PTR_ASSERT(m_ptr != NULL); 103 return m_ptr; 104 } 105 106 operator bool() const 107 { 108 return m_ptr != NULL; 109 } 110 111 //取得原始指針 112 T* getPointer() 113 { 114 PTR_ASSERT(m_ptr != NULL); 115 return m_ptr; 116 } 117 118 //得到引用計數 119 int getRefCount() 120 { 121 PTR_ASSERT(m_iRefCount != NULL); 122 return *m_iRefCount; 123 } 124 125 126 private: 127 void RefCountInit() 128 { 129 m_iRefCount = new int(1); 130 } 131 132 void RefCountIncrease() 133 { 134 if (m_iRefCount != NULL) 135 { 136 ++(*m_iRefCount); 137 } 138 } 139 140 void RefCountDecrease() 141 { 142 if (m_iRefCount != NULL && --(*m_iRefCount) == 0) 143 { 144 m_deleter(m_ptr); 145 delete m_iRefCount; 146 m_ptr = NULL; 147 m_iRefCount = NULL; 148 } 149 } 150 151 private: 152 int* m_iRefCount; //引用計數 153 154 T* m_ptr; //對象指針 155 156 deleter m_deleter; //刪除器 157 }; 158 159 _SMART_PTR_END 160 #endif // !__SHARE_PTR_H__
main函數測試函數
1 #include "share_ptr.h" 2 #include <memory> 3 4 class Test 5 { 6 public: 7 Test() 8 { 9 std::cout << "construct.." << std::endl; 10 } 11 12 void method() 13 { 14 std::cout << "welcome Test.." << std::endl; 15 } 16 17 ~Test() 18 { 19 std::cout << "destruct.." << std::endl; 20 } 21 }; 22 23 int main() 24 { 25 Test* t1 = new Test(); 26 27 _SMART_PTR shared_ptr<Test> shptr(t1); 28 29 _SMART_PTR shared_ptr<Test> shptr1(shptr); 30 31 _SMART_PTR shared_ptr<Test> shptr2 = shptr1; 32 33 std::cout << "RefCount: " << shptr2.getRefCount() << std::endl; 34 35 shptr2->method(); 36 37 (*shptr2).method(); 38 39 if (shptr2) 40 { 41 std::cout << "ptr is exit " << std::endl; 42 } 43 44 45 46 return 0; 47 }
測試最後打印:測試
1 [yejy@yejy cmake-00]$ ./smartptr 2 construct.. 3 RefCount: 3 4 welcome Test.. 5 welcome Test.. 6 ptr is exit 7 destruct.. 8 [yejy@yejy cmake-00]$
shared_ptr主要需實現的功能點以下(如下總結引用自網絡,非原創):this
沒有參數構造的時候,初始化爲空,即對象和引用計數的兩個指針都爲0spa
使用指針爲參數構造時,擁有此指針,在沒有智能指針指向它時進行析構指針
智能指針複製時,兩個智能指針共同擁有內部指針,引用計數同時+1code
智能指針可使用智能指針或普通指針從新賦值。重載=操做符,對於智能指針賦值,須要考慮是否自賦值,以免將自身析構了後再從新賦值,而普通指針賦值給智能指針,則不須要考慮自賦值,由於二者自己是兩個類型對象
得到底層指針的訪問,定義getPtrPointer()
和getPtrCounter()
來分別返回底層指針和引用計數,定義operator bool()
來處理智能指針隱式轉換爲bool
的狀況
重載->
和×
操做符 ,來實現與普通指針相同的指針訪問
須要支持隱式指針類型轉換,static_cast
不支持而dynamic_cast
支持的轉換則使用Cast<T2>()
成員函數來解決。考慮定義友元類,以防止指向派生類的智能指針有權限訪問基類的內部對象;當轉型不成功時,返回爲空 (未實現)
若是一個裸指針直接用來建立兩個智能指針的話,指望的狀況是當兩個智能指針析構掉的時候,該指針會被delete兩次從而崩潰(這是shared_ptr
的特色)
不處理循環引用(也是shared_ptr
的特色),能夠經過與weak_ptr
協做來打破循環
實現deleter
機制