shared_ptr能和基于引用計(jì)數(shù)的智能指針混用嗎?
前言
我在上一篇文章中介紹了幾種誤用智能指針的例子。還有一種比較典型,就是混用兩種類型的智能指針。直接看代碼吧!
示例代碼
#include?"stdafx.h"
#include?
#include?
#include?"RefCountedPtr.h"
class?PBObject?:?public?RefCounted
{
public:
????virtual?double?Volume()?{?return?0.0;?}
};
class?PBWall?:?public?PBObject
{
public:
????virtual?double?Volume()?{?return?100.0;?}
????~PBWall()?{?std::cout?<std::endl;?}
};
void?Test()
{
????RefCountedPtr?pWall(new?PBWall()) ;
????std::shared_ptr?pSharedWall(pWall.get()) ;
}
int?_tmain(int?argc,?_TCHAR*?argv[])
{
????Test();
????return?0;
}
pWall 在析構(gòu)的時(shí)候會(huì)調(diào)用 Release() 遞減引用計(jì)數(shù)到 0,從而調(diào)用 delete。pSharedWall 拿著同樣的指針,在析構(gòu)的時(shí)候也會(huì)調(diào)用 delete 刪除同一塊地址。于是暴雷了!
那么有辦法把 RefCountPtr 類型的智能指針交給 shared_ptr 管理嗎?答案是肯定的,只需要把 Test() 改成看下面這樣即可:
void?Test()
{
????RefCountedPtr?pWall(new?PBWall()) ;
????std::shared_ptr?pSharedWall(pWall.get(),?
????????[](PBObject*?p){?/*?p->Release();?*/?}?//?use?customized?deleter,?do?nothing,?can't?call?p->Release();
????) ;
}
在構(gòu)造 shared_ptr 類型的智能指針的時(shí)候,可以傳遞一個(gè)自定義的 Deleter,這個(gè) Deleter 不需要做任何事情。
基于引用計(jì)數(shù)的智能指針的一個(gè)實(shí)現(xiàn)
基于引用計(jì)數(shù)的智能指針常用于 COM 編程中,下面的代碼是一份簡(jiǎn)要的實(shí)現(xiàn),感興趣的小伙伴兒可以看一看。畢竟,手機(jī)不太適合看代碼,也可以下載后在電腦上查看。
#include?"stdafx.h"
#include?
#include?
//?http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template?<class?Base>?class?RefCounted?:?public?Base
{
protected:
????virtual?~RefCounted()?{}
public:
????RefCounted()?{?m_refCount?=?0;?}
????RefCounted(RefCounted?const&?rhs)?{?m_refCount?=?0;?}
????RefCounted&?operator=(RefCounted?const&?rhs)?{?if?(this?!=?&rhs)?{?Base::operator=(rhs);?}?return?*this;?}
????int?GetRefCount()?const?{?return?m_refCount;?}
????int?AddRef()?const?{?return?++m_refCount;?}
????int?Release()?const
????{
????????int?refCount?=?--m_refCount;
????????if?(0?????????{
????????????return?refCount;
????????}
????????delete?this;
????????return?0;
????}
private:
????mutable?int?m_refCount;
};
class?IRefCounted
{
protected:
????virtual?~IRefCounted()?{}
public:
????virtual?int?AddRef()?const?=?0;
????virtual?int?Release()?const?=?0;
};
template<class?T>?class?RefCountedPtr
{
private:
????typedef?RefCountedPtr?this_type;
public:
????RefCountedPtr()?:?p_(0)?{}
????RefCountedPtr(T?*?p,?bool?add_ref?=?true)?:?p_(p)
????{
????????if?(p_?!=?0?&&?add_ref)?p_->AddRef();
????}
????template?RefCountedPtr(RefCountedPtr?const?&?rhs)?:?p_(rhs.get())
???? {
????????if?(p_?!=?0)?p_->AddRef();
????}
????RefCountedPtr(RefCountedPtr?const?&?rhs)?:?p_(rhs.p_)
????{
????????if?(p_?!=?0)?p_->AddRef();
????}
????~RefCountedPtr()
????{
????????if?(p_?!=?0)?p_->Release();
????}
????template<class?U>?RefCountedPtr?&?operator=(RefCountedPtr?const?&?rhs)
????{
????????this_type(rhs).swap(*this);
????????return?*this;
????}
????bool?operator==?(RefCountedPtr?const&?rhs)?const
????{
????????return?p_?==?rhs.p_;
????}
????template<class?U>?bool?operator==?(RefCountedPtr?const&?rhs)?const
????{
????????return?p_?==?rhs.get();
????}
????bool?operator!=?(RefCountedPtr?const&?rhs)?const
????{
????????return?p_?!=?rhs.p_;
????}
????template<class?U>?bool?operator!=?(RefCountedPtr?const&?rhs)?const
????{
????????return?p_?!=?rhs.get();
????}
????RefCountedPtr?&?operator=(RefCountedPtr?const?&?rhs)
????{
????????this_type(rhs).swap(*this);
????????return?*this;
????}
????RefCountedPtr?&?operator=(T?*?rhs)
????{
????????this_type(rhs).swap(*this);
????????return?*this;
????}
????T?*?get()?const
????{
????????return?p_;
????}
????T&?operator*()?const
????{
????????return?*p_;
????}
????T?*?operator->()?const
????{
????????return?p_;
????}
????void?swap(RefCountedPtr?&?rhs)
????{
????????T?*?tmp?=?p_;
????????p_?=?rhs.p_;
????????rhs.p_?=?tmp;
????}
private:
????T?*?p_;
};
附件
文中的 RefCounterPtr 實(shí)現(xiàn)可以參考附件,下載地址如下:
百度云盤鏈接: https://pan.baidu.com/s/1HpFELQf97pkximT5oGm2pg 提取碼: h7w8
CSDN:https://download.csdn.net/download/xiaoyanilw/13679955
總結(jié)
shared_ptr 的 Deleter 妙用無(wú)窮,本文只是其中的一個(gè)用處。
評(píng)論
圖片
表情
