weak_ptr和intrusive_ptr
1、weak_ptr
(1)、weak_ptr是为了配合shared_ptr而引入的智能指针,它更像是shared_ptr的一个助手,它不具有普通指针的行为,
没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。
(2)、2个重要接口:bool expired()const ;// 判断是否过期
lock()函数是弱指针的核心;
(3)、获得资源的观测权,但weak_ptr没有共享资源,它的构造不会引起引用计数的增加,它的析构也不会导致引用计数减少,
它只是一个静静的观察者。
2、使用weak_ptr
调用系统库的:
#include<iostream>#include<boost/smart_ptr.hpp>usingnamespacestd;usingnamespaceboost;intmain(void){int*p=newint(10);shared_ptr<int>sp(p);weak_ptr<int>wp(sp);//1、本身对wp的创建与析构是不会增加/减少use_count;cout<<wp.use_count()<<endl;//2、显示的是它所观测对象的引用计数器if(!wp.expired()){//没过期(use_count!=0,空间还没释放)shared_ptr<int>sp1=wp.lock();//3、wp的lock()函数在有效的前提下可以构造对象(构造的是所观测的对象)。//使use_count加1;}//失效的话,构建的是一个空对象,引用计数将不会在增加!!!}
3、weak_ptr源码剖析
结合shared_ptr和前面的所有,删除器,shared_array、weak_ptr给出模拟的部分代码:
模仿源代码,写出了最重要的函数:
#ifndef_CONFIG_H_#define_CONFIG_H_#include<iostream>usingnamespacestd;//#defineDISPLAY#endif//////////////////////////////////////////////////////////////////////////////////////////#ifndef_SHARED_PTR_H_#define_SHARED_PTR_H_#include"shared_count.h"template<classT>classweak_ptr;template<classT>classshared_ptr{friendclassweak_ptr<T>;typedefshared_ptr<T>this_type;public:template<classY,classD>shared_ptr(Y*p,Dd):px(p),pn(p,d){}//支持传递删除器shared_ptr(T*p=0):px(p),pn(p){#ifdefDISPLAYcout<<"Createshared_ptrobject!"<<endl;#endif}shared_ptr(shared_ptr<T>const&r):px(r.px),pn(r.pn){}shared_ptr<T>&operator=(shared_ptr<T>const&r){if(this!=&r){this_type(r).swap(*this);//调用拷贝构造,先创建一个无名临时的对象}return*this;}~shared_ptr(){#ifdefDISPLAYcout<<"Freeshared_ptrobject"<<endl;#endif}public:T&operator*()const{return*(get());}T*operator->()const{returnget();}T*get()const{returnpx;}public:longuse_count()const{returnpn.use_count();}boolunique()const{returnpn.unique();}voidreset(T*p){this_type(p).swap(*this);}voidswap(shared_ptr<T>&other){std::swap(px,other.px);//指针的交换pn.swap(other.pn);}public:template<classY>shared_ptr(weak_ptr<Y>const&r):pn(r.pn){px=r.px;}private:T*px;shared_countpn;};#endif/////////////////////////////////////////////////////////////////////////////////////////////////#ifndef_SHARED_COUNT_H_#define_SHARED_COUNT_H_#include"config.h"#include"sp_counted_base.h"#include"sp_counted_impl_xx.h"classshared_count{friendclassweak_count;public:template<classT>//此时类型不定,写模板函数shared_count(T*p):pi(newsp_counted_impl_xx<T>(p)){#ifdefDISPLAYcout<<"Createshared_coutobject!"<<endl;#endif}template<classY,classD>shared_count(Y*p,Dd):pi(0){typedefY*P;pi=newsp_counted_impl_pd<P,D>(p,d);}shared_count(shared_countconst&r):pi(r.pi){if(pi){pi->add_ref_copy();}}~shared_count(){#ifdefDISPLAYcout<<"Freeshared_countobject"<<endl;#endifif(pi){pi->release();}}public:longuse_count()const{returnpi!=0?pi->use_count():0;}boolunique()const{returnuse_count()==1;}voidswap(shared_count&r){sp_counted_base*tmp=r.pi;r.pi=pi;pi=tmp;}public:explicitshared_count(weak_countconst&r);private:sp_counted_base*pi;};/////////////////////////////////////////////////////template<classP,classD>classsp_counted_impl_pd:publicsp_counted_base{public:sp_counted_impl_pd(Pp,Dd):ptr(p),del(d){}public:voiddispose(){del(ptr);}private:Pptr;Ddel;};/////////////////////////////////////////////////////////////////////classweak_count{friendclassshared_count;public:weak_count(shared_countconst&r):pi(r.pi){if(pi!=0){pi->weak_add_ref();}}~weak_count(){if(pi){pi->weak_release();}}public:longuse_count()const{returnpi!=0?pi->use_count():0;}private:sp_counted_base*pi;};shared_count::shared_count(weak_countconst&r):pi(r.pi){if(pi){pi->add_ref_lock();}}#endif//////////////////////////////////////////////////////////////////////////////#ifndefSP_COUNTED_BASE_H_#defineSP_COUNTED_BASE_H_#include"config.h"classsp_counted_base{//抽象类public:sp_counted_base():use_count_(1),weak_count_(1){#ifdefDISPLAYcout<<"Createsp_counted_baseobject"<<endl;#endif}virtual~sp_counted_base(){#ifdefDISPLAYcout<<"Freesp_counted_baseobject"<<endl;#endif}public:virtualvoiddispose()=0;//纯虚函数voidrelease(){if(--use_count_==0){dispose();deletethis;}}public:longuse_count()const{returnuse_count_;}voidadd_ref_copy(){++use_count_;}voidweak_add_ref(){++weak_count_;}virtualvoiddestroy(){deletethis;}voidweak_release(){if(--weak_count_==0){destroy();}}booladd_ref_lock(){if(use_count==0){returnfalse;}++use_count_;returntrue;}private:longuse_count_;longweak_count_;};#endif/////////////////////////////////////////////////////////////////////////////////#ifndef_SHARED_ARRAY_H_#define_SHARED_ARRAY_H_#include"checked_delete.h"template<classT>classshared_array{public:typedefchecked_array_deleter<T>deleter;shared_array(T*p=0):px(p),pn(p,deleter()){}//无名对象~shared_array(){}public:T&operator[](inti)const{returnpx[i];}private:T*px;shared_countpn;//必须用到引用计数器对象};#endif////////////////////////////////////////////////////////////////////////////////////////////#ifndef_CHECKED_DELETE_H_#define_CHECKED_DELETE_H_template<classT>voidchecked_array_delete(T*x){delete[]x;}template<classT>structchecked_array_deleter{public:voidoperator()(T*x)const{checked_array_delete(x);}};#endif//////////////////////////////////////////////////////////////////////////////////////////////#ifndef_WEAK_PTR_H_#define_WEAK_PTR_H_#include"shared_ptr.h"template<classT>classshared_ptr;classshared_count;template<classT>classweak_ptr{friendclassshared_ptr<T>;friendclassshared_count;public:template<classY>weak_ptr(shared_ptr<Y>const&r):px(r.px),pn(r.pn){}~weak_ptr(){}public:longuse_count()const{pn.use_count();}boolexpired()const{returnpn.use_count()==0;}shared_ptr<T>lock()const{returnshared_ptr<T>(*this);}private:T*px;weak_countpn;};#endif///////////////////////////////////////////////////////////////////////////////////////////////////#ifndefSP_COUNTED_IMPL_XX_H_#defineSP_COUNTED_IMPL_XX_H_#include"sp_counted_base.h"template<classT>classsp_counted_impl_xx:publicsp_counted_base{public:sp_counted_impl_xx(T*p):px_(p){#ifdefDISPLAYcout<<"Createsp_counted_impl_xxobject"<<endl;#endif}~sp_counted_impl_xx(){#ifdefDISPLAYcout<<"Freesp_counted_impl_xxobject"<<endl;#endif}public:voiddispose(){deletepx_;}private:T*px_;};#endif///////////////////////////////////////////////////////////////////////////////////////////////////////#include<iostream>#include"shared_ptr.h"#include"shared_array.h"#include"weak_ptr.h"usingnamespacestd;intmain(void){int*p=newint(10);shared_ptr<int>sp(p);weak_ptr<int>wp(sp);if(!wp.expired()){shared_ptr<int>sp1=wp.lock();//返回真实的对象cout<<sp.use_count()<<endl;}cout<<sp.use_count()<<endl;}
这是这个智能指针的最主要的剖析,关键理清脉络,条理清晰一些,就可以分析出来!
4、intrusive_ptr的使用
适用情景:(1)、对内存的占用要求非常严格,不能有引用计数的内存开销;
(2)、这时的代码中已经有了引用计数机制管理的对象;
重点掌握如何使用:
(1)、两个方法必须重写(增加/减少引用计数)
(2)、必须自己编写管理引用计数的类
(3)、要封装到一个类中,在继承(把自己的类侵入到智能指针中进行管理)
具体使用的一个类子如下:
#include<iostream>#include<boost/smart_ptr.hpp>usingnamespacestd;usingnamespaceboost;//1、实现2个重要的函数template<classT>voidintrusive_ptr_add_ref(T*t){//增加引用计数t->add_ref_copy();}template<classT>voidintrusive_ptr_release(T*t){//减少引用计数t->release();}//2、提供管理对象classCounter{public:Counter():use_count_(0){}~Counter(){}public:voidadd_ref_copy(){++use_count_;}voidrelease(){if(--use_count_==0){deletethis;}}private:longuse_count_;};//3、定义自己的对象classTest;ostream&operator<<(ostream&out,constTest&t);classTest:publicCounter{friendostream&operator<<(ostream&out,constTest&t);public:Test(intd=0):data(d){}~Test(){}private:intdata;};ostream&operator<<(ostream&out,constTest&t){out<<t.data;returnout;}intmain(void){Test*pt=newTest(10);intrusive_ptr<Test>ip(pt);cout<<*ip<<endl;}
结果如下:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。