智能指针之 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

 

posted @ 2018-04-30 05:08  还在  阅读(7680)  评论(0编辑  收藏  举报