智能指針之 unique_ptr


  對於動態申請的內存,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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM