《C++侵入式智能指针的实现.docx》由会员分享,可在线阅读,更多相关《C++侵入式智能指针的实现.docx(13页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、C+侵入式智能指针的实现简介在现代C+编程中,智能指针给我们在资源管理上带来了很多好处,这里就不多说了。在工作中,我们常常会用智能指针来管理资源,其中最常用的就是引用计数类智能指针了 (shared_ptr)。资源共享型的智能指针有两种实现,一种是侵入式,一种是非侵入式。在教材里比较常见的是非侵入式的,它的实现完全放在智能指针模板里,模板类有一个用于 保存资源类对象的指针变量,和一个用于记录资源对象使用计数的指针变量,这两个东西是 所有的智能指针对象共享的,所以通过指针保存。而侵入式则不同,它的实现分散在智能指针模板和使用智能指针模板的类中:模板类只有一 个用于保存对象的指针变量,对象的计数放
2、在了资源类中。非侵入式智能指针,它的引用计数变量为了保证所有对象共享,需要用堆里的内存,所以需 要用new,这个都一样,不一样的是使用new的次数。侵入式智能指针的引用计数变量保存在对象里,因为对象是唯一的,所以引用计数也是唯一 的。相比非侵入式智能指针,它的好处是:1、一个资源对象无论被多少个侵入式智能指针包含,从始至终只有一个引用计数变量,不 需要在每一个使用智能指针对象的地方都new 一个计数对象,这样子效率比较高,使用内 存也比较少,也比较安全;2、因为引用计数存储在对象本身,所以在函数调用的时候可以直接传递资源对象地址,而 不用担心引用计数值丢失(非侵入式智能指针对象的拷贝,必须带着
3、智能指针模板,否则就 会出现对象引用计数丢失)。缺点是:I、资源类必须有引用计数变量,并且该变量的增减可以被侵入式智能指针模板基类操作, 这显得麻烦;return T return bool*/T* get() const(return _ptr;/*/operator bool() const* bricf 调用.* rcturn T* /T* operator-() const(if(Lptr)ihrowNullHandleExceptionO;)return _ptr;)/* brief 引用.* retum T&* /T& operator*。const(if(Lptr)(throwN
4、ullHandleExccption();)return *_ptr;)/* bricf是否有效.return _ptr ? true : false;* brief交换指针.* param other*/void swap(Shared_Ptr& other)(std:swap(_ptr, othcr._ptr);protected:/*/template inline voidShared_Ptr:throwNullHandleException() const throw Shared_PtrNull_Exception(shared_ptr null handle error); )/
5、* brief =判断.* param T* param U* brief抛出异常*/void throwNullHandleExceplion() const;public:T brief抛出异常.* param T* param file* param line,ptr;* param Ihs* param rhs * return bool*/templaleinline bool operator=(const Shared_Ptr& Ihs, const Shared_Ptr& rhs)T* 1 = lhs.get();U* r = rhs.gct(); if(l & r)retur
6、n *1 = *r: ) elsereturn !1 & !r;/* brief不等于判断.* param T* param U* param Ihs* param rhs * return bool*/tempiateinline bool operator!=(const Shared_Ptr& Ihs, const Shared_P(r& rhs)T* I = lhs.get();U* r = rhs.get(); if(l & r)return *1 != *r; elsereturn 11| r;* bricf小于判断,用于放在map等容器中.* param T* param U*
7、param Ihs* param rhs* rcturn bool*/templateinline bool operator(consl Shared_Plr& Ihs, const Shared_Plr& rhs) |T* 1 = lhs.get();U* r = rhs.get();if(l & r)return *1 *r;Ielse(return !1 & r;)使用示例class Test: public HandlcBase(n.Shared_Ptr myTes(Class = new Test();2、如果该类并不想使用智能指针,它还是会带着引用计数变量。另外,智能指针有一个无
8、法避免的问题,就是循环引用。侵入式智能指针实现两个要点:1 .将引用计数变量从资源类中抽离出来,封装成一个基类,该基类包含了引用计数变量。如 果一个类想使用智能指针,则只需要继承自该基类即可;2 .引用计数的基类,设计成模板类,接受引用计数类型作为参数,比如使用int类型或者原 子计数类型作为引用计数变量。默认情况下应该使用原子计数类型作为引用计数变量。3 .引用计数基类的构造函数、拷贝构造函数、析构函数应为protected,即该类只能通过继承 关系被使用。4 .拷贝构造函数并不拷贝引用计数基类的数据成员,而是重新将原子计数_alomic置为0 因为每个对象都有一个自己的引用计数,当发生对象
9、拷贝构造时,新的对象的计数应该置为 0,而不应该拷贝旧对象的计数。5 .赋值操作operator,比如A=B,同上面一样,只对资源类的成员进行拷贝,而不拷贝其 引用计数基类的数据成员。也就是说,将B的值赋给A, A的引用计数应该保持不变,而 不能将B的引用计数拷贝过来一一这是对象的拷贝,而不是智能指针的拷贝。首先实现引用计数基类(注:Atomic的实现这里就不给出了):* brief智能指针基类.* 所有需要智能指针支持的类都需要从该对象继承,* 内部采用引用计数Atomic实现,对象可以放在容器中:* /templateclass HandleBaseT(public:/*原子计数类型*/
10、typedef T atomic_type;* brief复制。引用计数不能被复制。* rcturn HandlcBasc&* /HandlcBaseT& opcrator=(const HandleBaseT&)(return *this;)/* brief增加计数* /void incRef() .atomic.inc_fasl(); /* brief减少计数,当计数=0时,且需要删除数据时,释放对象* /void decRef()(if(_a(omic.dec_and_test() & !_bNoDeleie)(_bNoDelete = true;delete this;)* brief
11、获取计数.* return int 计数值* /int getRef() const return _atoinic.get(); /* brief设置不自动释放.* param b 是否自动删除.true or false*/void setNoDelete(bool b) _bNoDelete = b; protected:brief构造函数*/HandleBaseT(): _atomic(0), _bNoDelete(false)/*brief拷贝构造,.atomic和_bNoDelete不能被拷贝,只能重置*/HandleBaseT(const HandleBaseT&): _atom
12、ic(0), _bNoDelete(false)/* brief 析构*/virtual -HandleBaseT() protected:/*计数*/atomic_type _atomic;/*是否自动删除*/bool_bNoDelete;/针对int类型计数变量的特化在类声明中定义的函数将自动inline,类外定义的函数需显式inlinetemplateoinline void HandleBaseT:incRef()+_atoniic;templateoinline void HandleBaseT:decRef()if(-_atomic = 0 & !_bNoDelete)_bNoDe
13、lete = true; delete this;templateoinline int HandlcBaseT:gctRef() const (return .atomic;/默认使用Atomic作为引用计数类型typedef HandleBaseT HandleBase;以上实现了计数基类,所有需要使用智能指针的对象必须继承自该类。智能指针模板类的实现需要关注的几个点:1 .初始化、赋值等操作需要考虑参数是原始指针、其他类型的智能指针初、用同一类型的智 能指针三种情况。2 .需要重载、=、!=几个操作(非成员函数),左右操作数使用两个模板参数。3 .赋值操作需要检查自我赋值。* bricf
14、空指针异常*/struct Shared_PtrNu 1 LException : public Exception (Shared_PtrNull_Exception(const string & buffer): Exception(buffer);Shared_PtrNull_Exception() throw();;/通过它定义智能指针,该智能指针通过引用计数实现, *可以放在容器中传递. * template T 必须继承于 HandleBase*/* brief智能指针模板类.*可以放在容器中,且线程安全的智能指针. *teinplateclass Shared_Ptr publi
15、c:/* 元素类型* /typedef T element_type;/* brief用原生指针初始化,计数+1. * param p* /Shared_Ptr(T* p = 0) (-Ptr = p;if(_ptr) _ptr-incRcf();* brief用其他智能指针r的原生指针初始化,计数+1. * param Y* param r*/templateSharcd_Ptr(const Sharcd_Ptr& r) (_ptr = r._ptr;if(,ptr) (_ptr-incRef();) )/* brief拷贝构造,计数+1.* param r* /Shared_Ptr(con
16、sl Shared_P(r& r) (_plr = r._ptr;if(,ptr)(_ptr-incRcf();* brief 析构* /-Sharcd_Ptr()if(,ptr)_ptr-decRef();)I/* bricf赋值,普通指针.* param p* return Shared_P(r&* /Shared_Ptr& operator=(T* p) (if(_ptr != p)if(p)| p-incRef();)T* ptr = _ptr;_ptr = p:if(plr)ptr-decRef();return *this;* brief赋值,其他类型智能指针.* param Y*
17、 param r* rcturn Shared_Ptr&*/templateShared_Ptr& operator=(const Shared_Ptr& r) (if(_ptr != r._ptr)(if(r._ptr)r._ptr-incRef();T* ptr = _ptr;_ptr - r _ptr;if(ptr)( ptr-decRef();)return *this;)木* brief赋值,该类型其他执政指针.* param r* return Shared_Ptr&* /Shared_Ptr& operator=(const Shared_Ptr& r)if(_ptr != r.
18、_ptr)if(r._ptr)(r._ptr-incRcf();T brief将其他原生类型的指针转换成当前类型的智能指针. * param Y* param p* return Shared_Ptr*/templatestatic Shared_Ptr dynamicCast(Y* p)(return Sharcd_Ptr(dynamic_cast(p); ptr = _ptr;_ptr = r._ptr;if(ptr)( ptr-decRef();)return *this;* brief将其他类型的智能指针换成当前类型的智能指针.* param Y* param r* return Shared_Ptr* /tcmplatcstatic Shared_Ptr dynamicCast(const Shared_Ptr& r) (return Shared_P(r(dynamic_cast(r._plr);)