智能指针之 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 [[email protected] code]# g++ -o unique unique_ptr_implement.cpp
 2 [[email protected] 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 [[email protected] code]# 

  从实现结果可以看出,unique_ptr保证一个动态对象只有一个unique_ptr对象所拥有,unique_ptr对象之间无法copy和赋值,只能进行动态内存对象的转移,转移时,原有的unique_ptr对象将不再拥有动态内存的访问权限,这样可以保证动态内存使用的安全性。在实现中构造函数提供了两个,一个使用默认删除器,另一个则需要我们构造时传入删除器,这样可以很好的进行资源自定义删除。 对于多个指针对象指向同一个动态内存对象,unique_ptr不适用,需使用share_ptr

原文地址:https://www.cnblogs.com/blog-yejy/p/8972858.html

时间: 2024-10-10 03:36:47

智能指针之 unique_ptr的相关文章

C++ Primer 学习笔记_56_STL剖析(十一)(原boost库):详解智能指针(unique_ptr(原scoped_ptr) 、shared_ptr 、weak_ptr源码分析)

注意:现在boot库已经归入STL库,用法基本上还和boost类似 在C++11中,引入了智能指针.主要有:unique_ptr, shared_ptr, weak_ptr. 这3种指针组件就是采用了boost里的智能指针方案.很多有用过boost智能指针的朋友,很容易地就能发现它们之间的关间: std boost 功能说明 unique_ptr scoped_ptr 独占指针对象,并保证指针所指对象生命周期与其一致 shared_ptr shared_ptr 可共享指针对象,可以赋值给shar

智能指针(三):unique_ptr使用简介

我们知道auto_ptr通过复制构造或者通过=赋值后,原来的auto_ptr对象就报废了.所有权转移到新的对象中去了.而通过shared_ptr可以让多个智能指针对象同时拥有某一块内存的访问权.但假如我们不希望多个内存块被多个智能指针对象共享,同时又不会像auto_ptr那样不知不觉的就让原来的auto_ptr对象失效,可咋整呢? 这个时候就要使用unique_ptr了,顾名思义嘛,unique是唯一的意思.说明它跟auto_ptr有点类似,就是同时只能有一个智能指针对象指向某块内存.但它还有些

智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的一些注意事项

当智能指针作为函数的参数或者返回值时,一直在纠结到底是用智能指针对象本身还是用原始指针.Herb Sutter大师的文章很好的解决了这个疑惑,参见网址: https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/ 总结起来如下 1. 不要传递shared_ptr本身,而是用原始指针.因为会有性能损失,原子操作的自增自减等. 使用f(widget *w) 不使用f(shared_ptr< widget >

C++11智能指针:unique_ptr

unique_ptr 1.概念 unique_ptr形如其名,与所指对象的内存紧密地绑定,不能与其他的unique_ptr类型的指针对象共享所指向对象的内存. 在cplusplus.com中,unique_ptr声明如下: // non-specialized template <class T, class D = default_delete<T>> class unique_ptr; // array specialization template <class T,

智能指针之unique_ptr

概述 与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象.当unique_ptr被销毁时,它所指向的对象也被销毁.同时,unique_ptr也没有类似于make_shared的标准库函数,当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针.因此初始化unique_ptr需要使用直接初始化的形式.例如: unique_ptr<double> p(new double(3.14)); // p指向一个值为3.14的double 并且,由于一个u

智能指针简介

智能指针用于解决常规指针所带来的内存泄露.重复释放.野指针等内存问题.智能指针基于这样的事实得以发挥作用:定义在栈中的智能指针,当超出其作用域时,会自动调用它的析构函数,从而可以释放其关联的内存资源. 之前C++标准库中定义的智能指针std::auto_ptr<T>,因其设计存在缺陷,所以已不再推荐使用.C++11引入了新的智能指针:unique_ptr.shared_ptr和weak_ptr. 一:unique_ptr unique_ptr类似于auto_ptr.两个unique_ptr实例

C++智能指针类模板

1.智能指针本质上是一个对象,这个对象可以像原生的一样来进行使用.原因是智能指针对象对应的类中,将指针相关的操作都进行了重载操作处理,所以才会达到这种像是原生的效果. 2.智能指针的意义: 现在C++开发库中最重要的类模板之一 C++中自动内存管理的主要手段 能够在很大程度上避开内存相关的问题 3.在QT中开发库中也提供了智能指针类模板,在STL标准库中也提供了,在c++的标准库忘了什么名了中也提供了智能指针类模板.所以智能指针类模板在C++中的地位很重要 4.STL中的智能指针类模板 auto

使用智能指针来管理对象 (基于RAII)

////一个简单的防止内存泄露的例子//void test() { //使用RAII的特性管理资源 //当智能指针unique_ptr被销毁时,它指向的对象也将被销毁 //这里test函数返回后 p将自动销毁 //unique_ptr<int[]> p( new int[200] ); //直接生成资源 //test函数返回后 p不能被正常销毁,就会造成资源泄露 //int* p = new int[200]; } int main() { while( 1 ) { test(); Sleep

c++11 智能指针

如果在程序中使用new从堆(自由存储区)分配内存,等到不需要时, 应使用delete将其释放.c++引入了智能指针auto_ptr, 以帮助自动完成这个过程. c++11摒弃了auto_ptr,并新增了三种智能指针:unique_ptr, shared_ptr, weak_ptr. 一. auto_ptr, unique_ptr , shared_ptr 头文件:  #include <memory> 用法:  auto_ptr<double>  A(new double); un