一:前言
大家应该明白智能指针的用途(管理动态对象的生命期)及好处。其他话就不多说了,直接看如何实现吧。你将会看到一个基于策略而实作出的无比强大,灵活的智能指针。参考的依然是《Modern C++ Design》一书。
二:原理说明
软件工程比其他工程有更丰富的多样性。你可以采用多种正确的方法去完成一件事情。一旦你选择了一种解决方案,便会有一大堆变化随之涌现,大至系统架构,小至程序片段。设计的多样性不断困扰着程序员。什么是最好的解决方法?是Events,还是Observers?Callbacks?virtuals?Template?任何设计结构上的问题,都有许多合适的解法,然而他们各有不同规格,并且各有优缺点。因此我们会面临各种不同的抉择。在“一个全功能型接口下实作所有东西”来满足我们各种不同的抉择显然会是失败的。
Policy有助于我们设计出安全,有效率,高度弹性且高复用性的“设计元素”。所谓Policy:定义一个小型Class或Class Template,他们只是单纯的完成某一方面的主题,在“遵循Policy接口”的前提下,你可以采用任何方法来实作Policy。接着你可以混合和匹配各种Policy,就可以完成一个“行为集”。
接下来采用此原理来实现我们的“智能指针”。实作完后大家可以认真理解Policy-base design(基于策略的设计)
三:实作
先来划分智能指针的主题(将其划分为5个):1.所管理的对象类型(T)2.拥有权策略(OwnerPolicy)3.安全检查策略(CheckPolicy)4.存储策略(StoragePolicy)5.线程策略(ThreadPolicy)。将每个主题作为HTSmartPtr的模板参数。一个主题仅涉及某一特定功能(他们提供统一的接口)。在遵循相应主题的接口下,你可以用不同的方式(Policy实现)完成该主题所需的功能。在每个主题下,你可以选择一种方式(Policy实现)来完成HTSmartPtr。没选择一种不同的Policy实现,你都会产生一种新的智能指针。因此甚至你可以说,可以产生无穷无尽的智能指针。
现在的问题我的主题一开始划分不正确怎么办。Policy只是很单纯的完成某一功能,因此你完全可以把原因划在A主题的Policy实现,改换成B主题下。这不需要动大量的代码,因为我们已将HTSmartPtr与Policy实现解耦。HTSmartPtr是由Policy实现组合产生的,只不过将这些Policy实现分类。而与HTSmartPt无关。
1. 拥有权策略(OwnerPolicy)
这里我仅提供拥有权策略的三个Policy实现:引用计数,引用计数的观察者,作用域为范围。
由于引用计数及观察者是配套使用的,因此一起讲:
引用计数:等同于boost中的share_ptr。采用该方案的智能指针是可以共享的。
观察者:等同于boost中的weak_ptr。采用该方案的智能指针是不允许外界访问其拥有的对象,必须转换为引用计数(此过程可以判断该对象是否还有效,有效防止类成员变量为指针类型可能出现的野指针问题)。
作用域为范围:用于局部变量,退出作用域时自动释放。不可共享。
看代码:
class HTCounter // 引用智能指针计数器
{
private:
HTCounter(HTCounter const & );
HTCounter& operator = (HTCounter const & );
public:
HTCounter() : m_nRefCount(0), m_nWeakCount(0) {}
void RefAdd() {++m_nRefCount;}
bool RefRelease() {--m_nRefCount; return m_nRefCount == 0;}
HT_UINT GetRefCount() { return m_nRefCount; }
void WeakAdd() {++m_nWeakCount;}
bool WeakRelease() {--m_nWeakCount; return m_nWeakCount == 0;}
HT_UINT GetWeakCount() { return m_nWeakCount; }
void Swap(HTCounter& rhs)
{ std::swap(m_nRefCount, rhs.m_nRefCount); std::swap(m_nWeakCount, rhs.m_nWeakCount);}
private:
HT_UINT m_nRefCount; // 实际引用计数值
HT_UINT m_nWeakCount; // 观察者的引用计数值
};
template <class P>
class WeakCounted;
template <class P>
class RefCounted // 引用计数
{
template <typename T> friend class WeakCounted;
public:
RefCounted() : m_pCount(0) {}
RefCounted(const RefCounted& rhs) : m_pCount(rhs.m_pCount) {}
template <typename P1>
RefCounted(const WeakCounted<P1>& rhs) : m_pCount(reinterpret_cast<const WeakCounted<P1>&>(rhs).ValidCounter()) {}
template <typename P1>
RefCounted(const RefCounted<P1>& rhs) : m_pCount(reinterpret_cast<const RefCounted&>(rhs).m_pCount)
{}
void NewCount()
{
m_pCount = static_cast<HTCounter*>(
HTMemSmall<>::operator new(sizeof(HTCounter)));
assert(m_pCount);
new (m_pCount)HTCounter;
m_pCount->RefAdd();
}
P Clone(const P& val)
{
if (m_pCount)
m_pCount->RefAdd();
return m_pCount ? val : HT_NULL;
}
bool Release(const P&)
{
if (m_pCount && m_pCount->RefRelease())
{
// 当引用计数、观察者计数均为0时释放计数器
if (!m_pCount->GetWeakCount())
{
m_pCount->~HTCounter();
HTMemSmall<>::operator delete(m_pCount, sizeof(HTCounter));
m_pCount = 0;
}
return true;
}
return false;
}
void Swap(RefCounted& rhs)
{
std::swap(m_pCount, rhs.m_pCount);
}
private:
HTCounter* m_pCount;
};
template <class P>
class WeakCounted // 观察者计数
{
public:
WeakCounted() : m_pCount(0) {}
WeakCounted(const WeakCounted& rhs) : m_pCount(rhs.m_pCount) {}
template <typename P1>
WeakCounted(const RefCounted<P1>& rhs) : m_pCount(reinterpret_cast<const RefCounted<P1>&>(rhs).m_pCount) {}
template <typename P1>
WeakCounted(const WeakCounted<P1>& rhs) : m_pCount(reinterpret_cast<const WeakCounted&>(rhs).m_pCount) {}
void NewCount() { assert(false); }
P Clone(const P& val)
{
if (m_pCount)
m_pCount->WeakAdd();
return val;
}
bool Release(const P&)
{
if (m_pCount && m_pCount->WeakRelease())
{
// 当引用计数、观察者计数均为0时释放计数器
if (!m_pCount->GetShareCount())
{
HTMemSmall<>::operator delete(m_pCount, sizeof(HTCounter));
m_pCount = 0;
}
}
return false;
}
HTCounter* ValidCounter() const
{
// 当引用计数非0
if (m_pCount && m_pCount->GetShareCount())
return m_pCount;
return HT_NULL;
}
void Swap(WeakCounted& rhs)
{ std::swap(m_pCount, rhs.m_pCount); }
template <typename T> friend class RefCounted;
private:
HTCounter* m_pCount;
};
template <class P>
class OwnerScoped
{
public:
void NewCount() {}
bool Release(const P&) { return true; }
};
2. 安全检查策略(CheckPolicy)
这里仅提供两种Plicy实现:CheckNo(不进行任何检查),CheckAssert(提领前进行assert检查是否为null)。
CheckNo: 不提供任何检验
CheckAssert:// 提领前断言检验
template <class P>
struct CheckNo
{
CheckNo() {}
template <class P1>
CheckNo(const CheckNo<P1>&) {}
static void OnDefault(const P&) {}
static void OnInit(const P&) {}
static void OnDereference(const P&) {}
static void Swap(CheckNo&) {}
};
template <class P>
struct CheckAssert
{
CheckAssert() {}
template <class P1>
CheckAssert(const CheckAssert<P1>&) {}
template <class P1>
CheckAssert(const CheckNo<P1>&) {}
static void OnDefault(const P&) {}
static void OnInit(const P&) {}
static void OnDereference(P val)
{
assert(val);
(void) val;
}
static void Swap(CheckAssert&) {}
};
3. 存储策略(StoragePolicy):
这里仅提供三种Policy实现:StorageNo(不为所管理的对象分配内存),StoragePool(在内存池中分配对象),StorageNew(即使用new 分配对象,delete释放对象)。
StorageNo:不含分配对象内存功能
StoragePool:在内存池中为对象分配空间,这里选用的是HTMemFlex,可参看内存分配部分
StorageNew:使用new分配,delete释放
template <typename T>
class HTStorageNo
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T* stored_type;
HTStorageNo() : m_pT(0) {}
HTStorageNo(const HTStorageNo&) {}
template <class U>
HTStorageNo(const HTStorageNo<U>&);// {}
// template <class U>
// HTStorageNo(const YKStorageChunk<U>&) {}
void Create() { assert(false); }
void Destroy() { assert(false); }
pointer operator-> () const { BOOST_STATIC_ASSERT(0); return m_pT;}
reference operator* () const { BOOST_STATIC_ASSERT(0); return *m_pT;}
void Swap(HTStorageNo& rhs)
{ std::swap(m_pT, rhs.m_pT); }
friend inline pointer GetImpl(const HTStorageNo& sp)
{ return sp.m_pT; }
friend inline const stored_type& GetImplRef(const HTStorageNo& sp)
{ return sp.m_pT; }
friend inline stored_type& GetImplRef(HTStorageNo& sp)
{ return sp.m_pT; }
private:
stored_type m_pT;
};
template <typename T>
class HTStorageNew
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T* stored_type;
void Create() { m_pT = new T(); }
void Destroy() { delete m_pT; m_pT = 0; }
pointer operator-> () const {return m_pT;}
reference operator* () const {return *m_pT;}
void Swap(HTStorageNew& rhs)
{std::swap(m_pT, rhs.m_pT);}
friend inline pointer GetImpl(const HTStorageNew& sp)
{return sp.m_pT;}
friend inline const stored_type& GetImplRef(const HTStorageNew& sp)
{return sp.m_pT;}
friend inline stored_type& GetImplRef(HTStorageNew& sp)
{return sp.m_pT;}
private:
stored_type m_pT;
};
template <typename T>
class HTStoragePool : public HTMemFlex<T>
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T* stored_type;
public:
HTStoragePool() : m_pT(0) {}
HTStoragePool(const HTStoragePool&) {}
template <class U>
HTStoragePool(const HTStoragePool<U>&) {}
// template <class U>
// HTStoragePool(const YKStorageNo<U>&) {}
HTStoragePool(const stored_type& p) : m_pT(p) {}
~HTStoragePool() {}
void Create() { m_pT = Allocate(sizeof(value_type)); }
void Destroy() { Deallocate(m_pT); m_pT = 0; }
pointer operator-> () const {return m_pT;}
reference operator* () const {return *m_pT;}
void Swap(HTStoragePool& rhs)
{std::swap(m_pT, rhs.m_pT);}
friend inline pointer GetImpl(const HTStoragePool& sp)
{return sp.m_pT;}
friend inline const stored_type& GetImplRef(const HTStoragePool& sp)
{return sp.m_pT;}
friend inline stored_type& GetImplRef(HTStoragePool& sp)
{return sp.m_pT;}
private:
stored_type m_pT;
};
4. 线程策略(ThreadPolicy)
两个Policy实现:ThreadSingle(单线程实现),ThreadMulti(多线程实现)
ThreadSingle:不用加锁保护,用于单线程环境。
ThreadMulti:可用于多线程环境。
暂不实现该策略,等实现完线程部分再来实在该策略。
5. 将一切组装起来
template <typename T,
template <class> class OwnerPolicy = RefCounted,
template <class> class CheckPolicy = CheckNo,
template <class> class StoragePolicy = HTStoragePool>
class HTSmartPtr : public StoragePolicy<T>
, public OwnerPolicy<typename StoragePolicy<T>::pointer>
, public CheckPolicy<typename StoragePolicy<T>::stored_type>
{
typedef StoragePolicy<T> MP;
typedef OwnerPolicy<typename StoragePolicy<T>::pointer> OP;
typedef CheckPolicy<typename StoragePolicy<T>::stored_type> KP;
public:
typedef typename MP::reference reference;
typedef typename MP::const_reference const_reference;
typedef typename MP::pointer pointer;
typedef typename MP::const_pointer const_pointer;
typedef typename MP::value_type value_type;
public:
HTSmartPtr(bool bNew = false) // 需要分配对象则传true
{
if (bNew)
{
NewObj();
}
}
void NewObj()
{
assert(!ValidObj());
Create();
NewCount();
}
HTSmartPtr(int rhs) // 只接受HT_NULL,不接受裸指针
{
assert(rhs == HT_NULL);
HTSmartPtr temp;
temp.Swap(*this);
}
HTSmartPtr(HTSmartPtr& rhs)
: MP(rhs), OP(rhs), KP(rhs)
{
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
HTSmartPtr(const HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
: MP(rhs), OP(rhs), KP(rhs)
{
GetImplRef(*this) = OP::Clone(HT_Safe_DownCast<pointer>(GetImplRef(rhs)));
}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
HTSmartPtr(HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
: MP(rhs), OP(rhs), KP(rhs)
{
GetImplRef(*this) = OP::Clone(HT_Safe_DownCast<pointer>(GetImplRef(rhs)));
}
HTSmartPtr& operator= (HTSmartPtr& rhs)
{
HTSmartPtr temp(rhs);
temp.Swap(*this);
return *this;
}
HTSmartPtr& operator= (int rhs)
{
assert(rhs == HT_NULL);
HTSmartPtr temp;
temp.Swap(*this);
return *this;
}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
HTSmartPtr& operator= (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
{
HTSmartPtr temp(rhs);
temp.Swap(*this);
return *this;
}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
HTSmartPtr& operator= (HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
{
HTSmartPtr temp(rhs);
temp.Swap(*this);
return *this;
}
void Swap(HTSmartPtr& rhs)
{
OP::Swap(rhs);
KP::Swap(rhs);
MP::Swap(rhs);
}
~HTSmartPtr()
{
if (OP::Release(GetImpl(*static_cast<MP*>(this))))
{
Destroy();
}
}
pointer operator-> ()
{
KP::OnDereference(GetImplRef(*this));
return MP::operator ->();
}
pointer operator-> () const
{
KP::OnDereference(GetImplRef(*this));
return MP::operator ->();
}
reference operator* ()
{
KP::OnDereference(GetImplRef(*this));
return MP::operator *();
}
reference operator* () const
{
KP::OnDereference(GetImplRef(*this));
return MP::operator *();
}
inline friend HT_BOOL operator==(const HTSmartPtr& lhs, const_pointer rhs)
{ return GetImpl(lhs) == rhs; }
inline friend HT_BOOL operator==(const_pointer lhs, const HTSmartPtr& rhs)
{ return rhs == lhs; }
inline friend HT_BOOL operator!=(const HTSmartPtr& lhs, const_pointer rhs)
{ return !(lhs == rhs); }
inline friend HT_BOOL operator!=(const_pointer lhs, const HTSmartPtr& rhs)
{ return rhs != lhs; }
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
inline HT_BOOL operator== (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
{return *this == GetImpl(rhs);}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
inline bool operator!= (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
{return !(*this == rhs);}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
inline bool operator< (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
{return !(*this < rhs);}
template <typename T1,
template <class> class OP1,
template <class> class KP1,
template <class> class MP1>
inline bool operator> (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
{return !(*this > rhs);}
inline pointer GetValue()
{ return GetImpl(*this); }
inline pointer GetValue() const
{ return GetImpl(*this); }
inline bool ValidObj()
{ return GetImpl(*this) != 0; }
inline bool ValidObj() const
{ return GetImpl(*this) != 0; }