對於動態申請的內存,C++語言為我們提供了new和delete運算符, 而沒有像java一樣,提供一個完整的GC機制,因此對於我們申請的動態內存,我們需要時刻記得釋放,且不能重復釋放,釋放后不能再去使用... 因此在使用時造成很多不便,且容易出現很多問題,一旦出問題就造成core dump,程序直接掛掉 , 這個時候,智能指針的優勢就體現出來了,智能指針符合RAII原則,資源獲取就是初始化,在對象析構時,將資源進行釋放,對動態內存做到一個比較好的管理
unique_ptr 持有對對象的獨有權—兩個unique_ptr不能指向一個對象,不能進行復制操作只能進行移動操作
unique_ptr擁有所有auto_ptr的功能,且unique_ptr通過將復制構造和賦值操作符私有化,將對象的所有權獨有,很好的將auto_ptr的安全問題給規避掉了,unique_ptr的其他特點包括:1.提供刪除器釋放對象,允許用戶自定義刪除器 2.添加了對象數組的偏特化實現,new[],delete[] 3.使用C++ 11的右值引用特性,實現所有權轉移 std::move()
本次實現,將unique_ptr的基本接口進行了實現,基本包括了unique_ptr的功能 (編譯平台:Linux centos 7.0 編譯器:gcc 4.8.5 )
使用std::unique_ptr時,需要#include <memory>頭文件,具體使用代碼如下(文件名:test_ptr.cpp):
1 #include <memory> 2 #include <iostream> 3 4 using namespace std; 5 6 class Test 7 { 8 public: 9 Test() 10 { 11 cout << "construct.." << endl; 12 } 13 14 ~Test() 15 { 16 cout << "destruct.." << endl; 17 } 18 }; 19 20 void test() 21 { 22 23 } 24 25 int main() 26 { 27 //auto_ptr 28 Test* p = new Test(); 29 auto_ptr<Test> ap(p); 30 31 //unique_ptr 32 Test* p1 = new Test(); 33 unique_ptr<Test> up(new Test()); 34 unique_ptr<Test> up1(move(up)); 35 36 37 38 //unique_ptr<Test> up2 = up; 39 40 unique_ptr<int> up3(new int(5)); 41 42 return 0; 43 }
具體實現代碼如下,沒有對動態對象數組及std::move()進行實現,動態對象數組實現代碼和這差不多,寫個模板偏特化即可,至於std::move()則和成員函數release()類似,轉移所有權(文件名:unique_ptr_implement.cpp):
1 #include <iostream> 2 #include <assert.h> 3 4 using namespace std; 5 6 #define PTR_ASSERT(x) assert(x) 7 8 template<class T> 9 struct defalute_deleter 10 { 11 void defalute_deleter_method() 12 { 13 cout << "deleter method..." << endl; 14 } 15 void operator()(T* ptr) 16 { 17 if(ptr != NULL) 18 { 19 cout << "default deleter....." << endl; 20 delete ptr; 21 ptr = NULL; 22 } 23 } 24 }; 25 26 template<typename T, typename deleter = defalute_deleter<T> > 27 class unique_ptr 28 { 29 public: 30 explicit unique_ptr(T* ptr = NULL); 31 32 unique_ptr(T* ptr, deleter d); 33 34 ~unique_ptr(); 35 36 T* get(); 37 38 void reset(T* ptr = NULL); 39 40 deleter& getDeleter(); 41 42 T* release(); 43 44 public: 45 T& operator*(); 46 47 T* operator->(); 48 49 operator bool() const; 50 51 private: 52 unique_ptr(unique_ptr& up); 53 54 unique_ptr& operator = (unique_ptr& up); 55 56 private: 57 T* m_ptr; 58 59 deleter m_deleter; 60 }; 61 62 template<typename T, typename deleter> 63 unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */, deleter d) 64 { 65 if(ptr != NULL) 66 { 67 m_ptr = ptr; 68 m_deleter = d; 69 } 70 } 71 72 template<typename T, typename deleter> 73 unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */) 74 { 75 if(ptr != NULL) 76 { 77 m_ptr = ptr; 78 } 79 } 80 81 template<typename T, typename deleter> 82 unique_ptr<T, deleter>::~unique_ptr() 83 { 84 if(m_ptr != NULL) 85 { 86 m_deleter(m_ptr); 87 m_ptr = NULL; 88 } 89 } 90 91 template<typename T, typename deleter> 92 T& unique_ptr<T, deleter>::operator*() 93 { 94 PTR_ASSERT(m_ptr != NULL); 95 96 return *m_ptr; 97 } 98 99 template<class T, class deleter> 100 T* unique_ptr<T, deleter>::operator->() 101 { 102 PTR_ASSERT(m_ptr != NULL); 103 104 return m_ptr; 105 } 106 107 template<typename T, typename deleter> 108 T* unique_ptr<T, deleter>::get() 109 { 110 return m_ptr; 111 } 112 113 template<typename T, typename deleter> 114 void unique_ptr<T, deleter>::reset(T* ptr) 115 { 116 T* old_ptr = m_ptr; 117 m_ptr = ptr; 118 119 if(old_ptr != NULL) 120 { 121 m_deleter(old_ptr); 122 old_ptr = NULL; 123 } 124 } 125 126 template<typename T, typename deleter> 127 deleter& unique_ptr<T, deleter>::getDeleter() 128 { 129 return m_deleter; 130 } 131 132 template<typename T, typename deleter> 133 T* unique_ptr<T, deleter>::release() 134 { 135 T* pTemp = m_ptr; 136 m_ptr = NULL; 137 138 return pTemp; 139 } 140 141 template<typename T, typename deleter> 142 unique_ptr<T, deleter>::operator bool() const 143 { 144 return m_ptr != NULL; 145 } 146 147 148 //Test class 149 class Test 150 { 151 public: 152 Test() 153 { 154 cout << "construct.." << endl; 155 } 156 157 ~Test() 158 { 159 cout << "destruct.." << endl; 160 } 161 162 void method() 163 { 164 cout << "welcome Test.." << endl; 165 } 166 }; 167 168 //custom deleter 169 template <class T> 170 struct custom_deleter 171 { 172 void deleter_method() 173 { 174 cout << "custom deleter method..." << endl; 175 } 176 177 void operator()(T* ptr) 178 { 179 cout << "custom deleter... " << endl; 180 delete ptr; 181 ptr = NULL; 182 } 183 }; 184 185 186 int main() 187 { 188 //default deleter 189 cout << "=======default deleter====interface test begin: ========== " << endl; 190 unique_ptr<Test> up(new Test()); 191 192 cout << "operator ->: " << endl; 193 up->method(); 194 195 cout << "operator *: " << endl; 196 (*up).method(); 197 198 cout << "operator bool: " << endl; 199 if(up){ cout<< "obj is exit" << endl;} 200 201 cout << "get: " << endl; 202 up.get()->method(); 203 204 cout << "getDeleter: " << endl; 205 defalute_deleter<Test> del = up.getDeleter(); 206 del.defalute_deleter_method(); 207 208 cout << "release: " << endl; 209 unique_ptr<Test> up1(up.release()); 210 211 //if take this, will die 212 //(*up).method(); 213 214 cout << "reset: " << endl; 215 up1.reset(); 216 217 //Custom deleter 218 cout << "=======Custom deleter====interface test begin: ========== " << endl; 219 custom_deleter<Test> d; 220 unique_ptr<Test, custom_deleter<Test> > up_custom_dele(new Test(), d); 221 222 cout << "operator ->: " << endl; 223 up_custom_dele->method(); 224 225 cout << "operator *: " << endl; 226 (*up_custom_dele).method(); 227 228 cout << "operator bool: " << endl; 229 if(up_custom_dele){ cout<< "obj is exit" << endl;} 230 231 cout << "get: " << endl; 232 up_custom_dele.get()->method(); 233 234 cout << "getDeleter: " << endl; 235 custom_deleter<Test> custom_del = up_custom_dele.getDeleter(); 236 custom_del.deleter_method(); 237 238 cout << "release: " << endl; 239 unique_ptr<Test> up3(up_custom_dele.release()); 240 241 //if take this, will die 242 //(*up_custom_dele).method(); 243 244 cout << "reset: " << endl; 245 up3.reset(); 246 247 248 return 0; 249 }
執行代碼,打印如下:
1 [root@localhost code]# g++ -o unique unique_ptr_implement.cpp 2 [root@localhost code]# ./unique 3 =======default deleter====interface test begin: ========== 4 construct.. 5 operator ->: 6 welcome Test.. 7 operator *: 8 welcome Test.. 9 operator bool: 10 obj is exit 11 get: 12 welcome Test.. 13 getDeleter: 14 deleter method... 15 release: 16 reset: 17 default deleter..... 18 destruct.. 19 =======Custom deleter====interface test begin: ========== 20 construct.. 21 operator ->: 22 welcome Test.. 23 operator *: 24 welcome Test.. 25 operator bool: 26 obj is exit 27 get: 28 welcome Test.. 29 getDeleter: 30 custom deleter method... 31 release: 32 reset: 33 default deleter..... 34 destruct.. 35 [root@localhost code]#
從實現結果可以看出,unique_ptr保證一個動態對象只有一個unique_ptr對象所擁有,unique_ptr對象之間無法copy和賦值,只能進行動態內存對象的轉移,轉移時,原有的unique_ptr對象將不再擁有動態內存的訪問權限,這樣可以保證動態內存使用的安全性。在實現中構造函數提供了兩個,一個使用默認刪除器,另一個則需要我們構造時傳入刪除器,這樣可以很好的進行資源自定義刪除。 對於多個指針對象指向同一個動態內存對象,unique_ptr不適用,需使用share_ptr