C++11 智能指针
最近要使用C++11的智能指针,补充下博客。
参考博客:https://www.cnblogs.com/wxquare/p/4759020.html
重要文档:http://en.cppreference.com/w/cpp/memory/shared_ptr
1、std::shared_ptr
shared_ptr是一个模板类,封装了普通的指针,增加了一个引用计数。每一个shared_ptr的拷贝都指向相同的内存,在最后一个shared_ptr析构时,内存才会被释放。这样一个类也是可以模拟实现的。
1 template <typename T> 2 class SmartPointer { 3 public: 4 //构造函数 5 SmartPointer(T* p=0): _ptr(p), _reference_count(new size_t){ 6 if(p) 7 *_reference_count = 1; 8 else 9 *_reference_count = 0; 10 } 11 //拷贝构造函数 12 SmartPointer(const SmartPointer& src) { 13 if(this!=&src) { 14 _ptr = src._ptr; 15 _reference_count = src._reference_count; 16 (*_reference_count)++; 17 } 18 } 19 //重载赋值操作符 20 SmartPointer& operator=(const SmartPointer& src) { 21 if(_ptr==src._ptr) { 22 return *this; 23 } 24 releaseCount(); 25 _ptr = src._ptr; 26 _reference_count = src._reference_count; 27 (*_reference_count)++; 28 return *this; 29 } 30 31 //重载操作符 32 T& operator*() { 33 if(ptr) { 34 return *_ptr; 35 } 36 //throw exception 37 } 38 //重载操作符 39 T* operator->() { 40 if(ptr) { 41 return _ptr; 42 } 43 //throw exception 44 } 45 //析构函数 46 ~SmartPointer() { 47 if (--(*_reference_count) == 0) { 48 delete _ptr; 49 delete _reference_count; 50 } 51 } 52 private: 53 T *_ptr; 54 size_t *_reference_count; 55 void releaseCount() { 56 if(_ptr) { 57 (*_reference_count)--; 58 if((*_reference_count)==0) { 59 delete _ptr; 60 delete _reference_count; 61 } 62 } 63 } 64 }; 65 66 int main() 67 { 68 SmartPointer<char> cp1(new char('a')); 69 SmartPointer<char> cp2(cp1); 70 SmartPointer<char> cp3; 71 cp3 = cp2; 72 cp3 = cp1; 73 cp3 = cp3; 74 SmartPointer<char> cp4(new char('b')); 75 cp3 = cp4; 76 }
内存模型图示:
有这个图上面那个代码就容易理解多了。
利用std::shared_ptr封装堆上内存,每一个shared_ptr的拷贝都指向相同的内存。在最后一个shared_ptr析构的时候,内存才会被释放。这机制就跟Java一模一样了,Java里参数传递说起来是两种,其实只有一种那就是值传递,Java参数传递分基础类型和引用类型,基础类型不用说就是值拷贝,引用类型其实也是值拷贝,拷贝的是对象地址,所以Java的参数传递像值传递又有地址传递的本质功能。
2、std::unique_ptr
unique_ptr也是封装一个内存,但不允许unique_ptr拷贝,就是始终只有一个unique_ptr对象指向一个内存块,不存在多个unique_ptr指向一个内存的情况。提供std::move函数完成指针移动。到现在也没想到std::unique_ptr有什么独特应用。
3、std::weak_ptr
weak_ptr指向一块内存,但不增加这个内存的引用计数。解决shared_ptr互相应用时造成无法删除内存的情况。
4、利用智能指针封装管理第三方库分配的内存
关于这点,参见博客:https://www.cnblogs.com/qicosmos/p/3889996.html 祁宇 著. 深入应用C++11:代码优化与工程级应用
在Qt项目工程里(我使用的是Qt5.6),要使用指针指针时,需要包含头文件#include <memory> ,不要写错成#include <memory.h>这是两个不同的文件,如果写成后面一个就会出现string in namespace std does not name a type(补充一句,STL的头文件全是不带.h的)。另外对C++11的支持也要看编译器,如果你的项目里可以使用nullptr,那么基本判断你的编译器支持C++11了。