智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而 造成了内存的浪费。
长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。
我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
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的实现原理:简单粗暴的防拷贝,下面简化模拟实现了一份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对象之间共享资源。
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是配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用记数的增加或减少。没有重载*和->但可以使用lock获得一个可用的shared_ptr对象。
实例:
#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;
}
总结: