现在的位置: 首页 > 综合 > 正文

智能指针(带有效性检查功能)

2013年05月01日 ⁄ 综合 ⁄ 共 3615字 ⁄ 字号 评论关闭

大概朋友们的一看到这个贴子的第一个感觉就是:又有闲得无聊 的家伙在造轮子了。
 呃,坦白的说,的确是这样。^_^
就算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;
  }
 }
}

 

 

抱歉!评论已关闭.