作用与用法
一种利用生命周期来控制程序资源的简单技术,类似于原生指针的,目的是解决异常等发生的内存安全问题。在构造对象时获取资源,对象析构时释放资源。
一般情况下,c/c++程序员担心的泄露有两种:堆泄露、系统资源泄露;
堆泄露:是指new/malloc realloc calloc 在堆上申请的内存,没有经过 new 或者free释放,导致部分空间无法在使用;
系统资源泄露:是指 程序使用系统分配的资源,比如套接字、文件描述符、管道等对应的函数,却没有正确的释放,导致系统资源的浪费。
发展史
c++98 引入auto_ptr 管理权转移,早期设计缺陷,一般情况下禁止使用
c++11引入unique_ptr 防拷贝
c++11引入shared_ptr 引用计数
c++11引入weak_ptr 循环引用 专门解决循环引用的问题 不是智能指针
template <class T>
class Smatrptr{
public:
Smatrptr(T* ptr=nullptr):_ptr(ptr){} //具有指针的行为,可以通过*去解引用,也可以通过->访问地址
~Smatrptr(){
if(_ptr)
delete _ptr;
}
T* operator ->(){ return _ptr;}
T& operator *(){ return *_ptr;}
private:
T *_ptr;
};
auto_ptr//管理权转移 但是不能进行拷贝构造,把之前管理的对象清空,会造成之前的资源不能访问
template <class T>
class auto_ptr{
public:
auto_ptr(T*ptr=nullptr):_ptr(ptr){ }
~auto_ptr(){ if(_ptr) delete _ptr;}
T* operator ->(){ return _ptr;}
T& operator *(){ return *_ptr;}
//拷贝构造 一旦发生拷贝构造,将p的资源托管给当前对象中,p与其所托管的资源断开;这样就解决一块空间被
//多个对象管理,而造成程序崩溃的问题
auto_ptr(const auto_ptr<T> &p):_ptr(p._ptr){
p._ptr=nullptr;
}
//赋值构造
auto_ptr& operator(auto_ptr<T>&p){
if(p!=this){
if(_ptr)
delete _ptr;
_ptr=p._ptr;
p._ptr=nullptr;
}
return *this;
}
private:
T* _ptr;
};
unique_ptr 设计非常简单粗暴, 防拷贝,也就时不能拷贝
template<class T>
class unique_ptr(){
unique(T *ptr=nullptr):_ptr(ptr){ }
T* operator ->(){ return _ptr;}
T& operator *(){ return *_ptr;}
unique_ptr(unique_ptr<T>p)=delete;//c++11的用法
unique_prt & opertaor= (unique_ptr<T>&p)=delete;
private:
T * _ptr;
}
share_prt 通过引用计数的方式来实现多个shared_ptr对象之间的共享资源
template<class T>
class shared_ptr{
shared_ptr(T*p=nullptr):_ptr(p),_pRefcount(new int(1)),_pMutex(new mutex){}
shared_ptr(shared_ptr<T>&p):_ptr(p._ptr),_pRefcount(p._pReefcount),_pMutex(p._pMutex){
add();
}
shared_ptr<T>& operator = (shared_ptr<T>&p){
if(this!=p){
release();
_ptr=p._ptr;
_pRefcount=p._pRefcount;
_pMutex=p._pMutex;
add();
}
return *this;
}
T* operator ->(){ return _ptr;}
T& operator *(){ return *_ptr;}
void add(){ _pMutec->lock();
++(*pRefcount);
_pMutex->unlock();
}
private:
void release(){
bool deleteflae=false;
_pMutes->lock();
if(--(*pRefcount)==0){
delete _ptr;
delete _pRefcount;
deletflag=true;
}
if(deleteflag) delete _pMutex;
}
T *_ptr;
int * _pRefcount;
mutex* _pMutex;
};
weak_ptr 是为了解决shared_ptr循环引用的问题;
srtuct list{
int data;
list* _prev;
list* _next;
};
shared_ptr<list>node1(new list);
shared_ptr<list>node2(new list); //程序会崩溃,
srtuct list{
int data;
weak_ptr<list> _prev;
weak_ptr<list> _next;
};
shared_ptr<list>node1(new list);
shared_ptr<list>node2(new list);//这样就可以了