智能指针是干什么的?
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。node
什么是内存泄漏?
内存泄漏指由于疏忽或错误形成程序未能释放已经再也不使用的内存的状况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,于是
形成了内存的浪费。
ios
内存泄漏有什么危害?
长期运行的程序出现内存泄漏,影响很大,如操做系统、后台服务等等,出现内存泄漏会致使响应愈来愈慢,最终卡死。网络
智能指针的原理
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。函数
咱们实际上把管理一份资源的责任托管给了一个对象。这种作法有两大好处:this
- 不须要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效。
智能指针的原理:
- RAII特性(是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络链接、互斥量等等)的简单技术)
- 重载operator*和opertaor->,具备像指针同样的行为。
auto_ptr指针
auto_ptr智能指针的缺点:当对象拷贝或者赋值后,前面的对象就悬空了。spa
auto_ptr智能指针的模拟实现
template<class T> class Auto_ptr{ public: Auto_ptr(T* ptr=nullptr):_ptr(ptr){} ~Auto_ptr(){ if (_ptr) delete _ptr; } Auto_ptr(Auto_ptr<T> &s)//拷贝构造会释放s对象的指针,形成s指针与管理对象断开联系 :_ptr (s._ptr){ s._ptr = NULL; } Auto_ptr<T>& operator=(Auto_ptr<T>& s){ if (this != &s._ptr){ if (_ptr) delete _ptr; _ptr = s._ptr; s._ptr = NULL; } return *this; } T& operator*(){ return *_ptr; } T* operator->(){ return _ptr; } private: T* _ptr; };
unique_ptr指针
unique_ptr的实现原理:简单粗暴的防拷贝,下面简化模拟实现了一份UniquePtr来了解它的原理操作系统
template<class T> class Unique_ptr{ public: Unique_ptr(T* ptr=nullptr):_ptr(ptr){} ~Unique_ptr(){ if (_ptr) delete _ptr; } T& operator*(){ return *_ptr; } T* operator->(){ return _ptr; } private: Unique_ptr(Unique_ptr<T> &s) :_ptr(s._ptr){ s._ptr = NULL; } Unique_ptr<T>& operator=(Unique_ptr<T>& s){ if (this != &s._ptr){ if (_ptr) delete _ptr; _ptr = s._ptr; s._ptr = NULL; } return *this; } private: T* _ptr; };
shared_ptr指针
shared_ptr的原理:经过引用计数的方式来实现多个shared_ptr对象之间共享资源。设计
- shared_ptr在其内部,给每一个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
- 在对象被销毁时(也就是析构函数调用),就说明本身不使用该资源了,对象的引用计数减一。
- 若是引用计数是0,就说明本身是最后一个使用该资源的对象,必须释放该资源;
- 若是不是0,就说明除了本身还有其余对象在使用该份资源,不能释放该资源,不然其余对象就成野指针了。
模拟实现:
template<class T> class Shared_ptr{ public: Shared_ptr(T* ptr) :_ptr(ptr),_pMutex(new mutex),_pRefrCount(new int(1)) {} ~Shared_ptr(){ Realse(); } Shared_ptr(const Shared_ptr<T>& sp) :_ptr(sp._ptr), _pRefrCount(sp._pRefCount), _pMutex(sp._pMutex) { AddRefCount(); } Shared_ptr<T>* operator=(const Shared_ptr<T>& sp){ if (this != sp){ Realse(); _ptr = sp._ptr; _pRefrCount = sp._pRefrCount; _pMutex = sp._pMutex; AddRefCount(); } return this; } T& operator*(){ return *_ptr; } T* operator->(){ return _ptr; } int UseCount(){ return *_pRefrCount; } T* Get(){ return _ptr; } void AddRefCount(){ _pMutex.lock(); ++(*_pRefrCount); _pMutex.unlock(); } private: void Realse(){ bool flag = false; _pMutex.lock(); if (--(*_pRefrCount) == 0){ delete _pRefCount; delete _ptr; flag = true; } _pMutex.unlock(); if (flag == true); delete _pMutex; } private: T* _ptr; int* _pRefrCount; mutex _pMutex; };
weak_ptr指针
weak_ptr是配合shared_ptr而引入的一种智能指针来协助shared_ptr工做,它能够从一个shared_ptr或另外一个weak_ptr对象构造,它的构造和析构不会引发引用记数的增长或减小。没有重载*和->但可使用lock得到一个可用的shared_ptr对象。3d
实例:指针
#include<iostream> #include<memory> using namespace std; struct ListNode { int _data; weak_ptr<ListNode> _prev; weak_ptr<ListNode> _next; ~ListNode(){ cout << "~ListNode()" << endl; } }; int main() { shared_ptr<ListNode> node1(new ListNode); shared_ptr<ListNode> node2(new ListNode); cout << node1.use_count() << endl; cout << node2.use_count() << endl; node1->_next = node2; node2->_prev = node1; cout << node1.use_count() << endl; cout << node2.use_count() << endl; system("pause"); return 0; }
总结:
- 智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
- auto_ptr智能指针:当对象拷贝或者赋值后,前面的对象就悬空了。
- unique_ptr智能指针:防止智能指针拷贝和复制。
- shared_ptr智能指针:经过引用计数的方式来实现多个shared_ptr对象之间共享资源。
- weak_ptr智能指针:能够从一个shared_ptr或另外一个weak_ptr对象构造,它的构造和析构不会引发引用记数的增长或减小。
- 对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,由于一个是指针,一个是类。能够经过make_shared函数或者经过构造函数传入普通指针。并能够经过get函数得到普通指针。