shared_ptr能和基于引用计数的智能指针混用吗?
编程难
共 427字,需浏览 1分钟
·
2020-12-22 18:45
前言
我在上一篇文章中介绍了几种误用智能指针的例子。还有一种比较典型,就是混用两种类型的智能指针。直接看代码吧!
示例代码
#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 << __FUNCTION__ << std::endl; }
};
void Test()
{
RefCountedPtr pWall(new PBWall()) ;
std::shared_ptr pSharedWall(pWall.get()) ;
}
int _tmain(int argc, _TCHAR* argv[])
{
Test();
return 0;
}
pWall
在析构的时候会调用 Release()
递减引用计数到 0
,从而调用 delete
。pSharedWall
拿着同样的指针,在析构的时候也会调用 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();
) ;
}
在构造 shared_ptr
类型的智能指针的时候,可以传递一个自定义的 Deleter
,这个 Deleter
不需要做任何事情。
基于引用计数的智能指针的一个实现
基于引用计数的智能指针常用于 COM
编程中,下面的代码是一份简要的实现,感兴趣的小伙伴儿可以看一看。毕竟,手机不太适合看代码,也可以下载后在电脑上查看。
#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 < refCount)
{
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
实现可以参考附件,下载地址如下:
百度云盘链接: https://pan.baidu.com/s/1HpFELQf97pkximT5oGm2pg 提取码: h7w8
CSDN:https://download.csdn.net/download/xiaoyanilw/13679955
总结
shared_ptr
的 Deleter
妙用无穷,本文只是其中的一个用处。
评论
基于OpenCV的手掌检测和手指计数
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达利用余弦定理使用OpenCV-Python实现手指计数与手掌检测。手检测和手指计数接下来让我们一起探索以下这个功能是如何实现的。OpenCVOpenCV(开源计算机视觉库)是一个开源计算机视觉和机器学习软件库。OpenCV的构建旨
小白学视觉
0