智能指针之 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
GitHub:https://github.com/Yejy813
博客园:https://www.cnblogs.com/blog-yejy
Copyright ©2018 yejy
【转载文章务必保留出处和署名,谢谢!】