大概朋友们的一看到这个贴子的第一个感觉就是:又有闲得无聊 的家伙在造轮子了。
呃,坦白的说,的确是这样。^_^
就算STL中的auto_ptr的所有权转移是不可接受的方案,那BOOST库中的虽说不太灵活,但用用也够了吧?再怎么吹毛求龇,LOKI库中的智能指针还不能满足要求吗?什么?要包含的头文件太多让你不爽?你分明是找碴!
以下纯属手闲得慌的结果,待会儿继续读LOKI去。
//以下是我的轮子 VC2003下通过
//////////////////////////////////////////////////////////////////////
//
// class name:
// autoptr
// description:
// autoptr is a light weight smart pointer. It can remember all pointers
// that have pointed to a object, and auto delete when no other pointers
// point to the object.
// Function Reset() means don't let the autoptr point to the object,
// If it's the last point, the object will be deleted.
// If require autoptr report pointer's validation, declaration should be:
// autoptr<int, NotArray<int>, ExceptionInvalidPointer<int> > pX(new int);
// Then if the internal pointer is NULL, and calls "pX->" or "*pX", it will
// throw an string of type char* indentify the name of type T.
// author:
// sproll
// date:
// 07-02-09
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <typeinfo.h>
template <typename T>
class NotArray
{
public:
NotArray(T* pt) : m_pt(pt){};
~NotArray(){};
void Del(){delete m_pt;};
T& Get(unsigned int uIndex)
{
if (uIndex != 0)
{
char* pcBuf = "operator [] on pointer which is not array.";
throw pcBuf;
}
else
{
return *m_pt;
}
};
private:
T* m_pt;
};
template <typename T>
class IsArray
{
public:
IsArray(T* pt) : m_pt(pt){};
~IsArray(){};
void Del(){delete [] m_pt;};
T& Get(unsigned int uIndex){return m_pt[uIndex];};
private:
T* m_pt;
};
template <typename T>
class NoException
{
public:
void CheckValid(void* p){};
};
template <typename T>
class ExceptionInvalidPointer
{
public:
ExceptionInvalidPointer()
: m_pstrName(typeid(T).name())
{
};
ExceptionInvalidPointer(const ExceptionInvalidPointer<T>& copy)
: m_pstrName(typeid(T).name())
{
};
~ExceptionInvalidPointer(){};
void CheckValid(T* p)
{
if (p == NULL)
{
char *pName = new char[strlen(m_pstrName) + 1];
strcpy(pName, m_pstrName);
throw pName;
}
};
private:
const char* m_pstrName;
};
template <typename T, typename ArrayCheck = NotArray<T>, typename ValidCheck = NoException<T> >
class autoptr
{
public:
autoptr() : m_pT(NULL), m_pnRefCount(NULL){};
autoptr(T* pT) : m_pT(pT), m_pnRefCount(pT? new int : NULL){if (m_pnRefCount) *m_pnRefCount = 1;};
autoptr(autoptr<T, ArrayCheck, ValidCheck>& ptr) : m_pT(ptr.m_pT), m_pnRefCount(ptr.m_pnRefCount) {if(m_pnRefCount) ++(*m_pnRefCount);};
~autoptr() {Reset();};
autoptr<T, ArrayCheck, ValidCheck>& operator= (autoptr<T, ArrayCheck, ValidCheck>& ptr);
T* operator-> () {ValidCheck chk; chk.CheckValid(m_pT); return m_pT;};
T& operator* () { ValidCheck chk; chk.CheckValid(m_pT); return *m_pT;};
bool operator==(const autoptr<T, ArrayCheck, ValidCheck>& ptr) const {return ptr->m_pT == m_pT;};
bool operator!=(const autoptr<T, ArrayCheck, ValidCheck>& ptr) const {return ptr->m_pT != m_pT;};
T& operator [] (unsigned int nIndex) {ArrayCheck arrchk(m_pT); return arrchk.Get(nIndex);};
//remove this auto_ptr from reference counting
void Reset();
//check if valid
bool Valid(){return m_pT != NULL;};
private:
//the object that is pointed
T* m_pT;
//reference count
int* m_pnRefCount;
};
template <typename T, typename ArrayCheck, typename ValidCheck>
autoptr<T, ArrayCheck, ValidCheck>& autoptr<T, ArrayCheck, ValidCheck>::operator= (autoptr<T, ArrayCheck, ValidCheck>& ptr)
{
if (this == &ptr)
{
return *this;
}
Reset();
m_pT = ptr.m_pT;
m_pnRefCount = ptr.m_pnRefCount;
if (m_pnRefCount)
{
++(*m_pnRefCount);
}
return *this;
}
template <typename T, typename ArrayCheck, typename ValidCheck>
void autoptr<T, ArrayCheck, ValidCheck>::Reset()
{
if (m_pnRefCount)
{
if (*m_pnRefCount == 1)
{
if (m_pT)
{
ArrayCheck arrchk(m_pT);
arrchk.Del();
m_pT = NULL;
}
if (m_pnRefCount)
{
delete m_pnRefCount;
m_pnRefCount = NULL;
}
}
else if (*m_pnRefCount > 1)
{
(*m_pnRefCount)--;
m_pT = NULL;
m_pnRefCount = NULL;
}
}
}