自定义的vector

 

标准模版容器类vector提供了统一的操作接口,但也有不方便的地方,主要是不便直接操纵其内存指针。

下面是我自定义的模版容器类XList<T>,已使用过多年,经过了比较充分的检验。

模版容器的一个关键操作就是当容器需要增加内存的时候(参考ReallocMem成员函数),如何拷贝对象,
有下面三种操作模式:
 A.可以对整个序列使用memcpy, memset, 这样对简单并且比较一般的对象效率高;
 B.要对每个对象使用operator=;
 C.使用对象的成员函数TransTo(数据转移,相当于右值引用),这样对复杂的对象高效安全;
这三种模式对应下面的三个类。

 还有一点值得说明的是,XList 提供了缓存机制(参考其数据成员pBufMem)。

 

//为方便使用该模板类, 其主要成员为public, 慎用该类!
template <typename X>
class XList //使用 memcpy, memset, 也使用了 operator=
{
public: 
 int xmem;
 int xnum;
 X* pxs; 
 
protected:
 X* pBufMem; //内存缓冲区(频繁使用时减少内存分配次数), 由使用者提供,不要释放!

public: 
 XList(int xm=0):xmem(0),xnum(0),pxs(0),pBufMem(0){
  if(xm>0) EnsureMem(xm);
 };
 ~XList(){
    FreeMem();   
 };

 XList(const XList& r){
  InitFrom(r);
 };
 void operator=(const XList& r){
  if(pxs){
   if(pxs!=pBufMem) delete[] pxs;
   pxs=0;
  }
  InitFrom(r);
 };

 bool IsTmpObj() const{//是否为临时对象,释放临时对象的内存是危险的!
  return (xnum>0 && xmem==0);
 };
 void TransFrom(XList& from){
  ASSERT(this!=&from);
  FreeMem();
  memcpy(this, &from, sizeof(XList<X>));
  memset(&from, 0, sizeof(XList<X>));
 };
 void TransTo(XList& to){
  ASSERT(this!=&to);
  to.FreeMem();
  memcpy(&to, this, sizeof(XList<X>));
  memset(this, 0, sizeof(XList<X>));
 };

 //初始化内存缓冲区
 void InitMemBuf(X* pBuf, int m){
  ASSERT(pxs==0 && m>0);
  pBufMem= pBuf;
  pxs= pBuf;
  xmem= m;
  xnum= 0;
 };

 void FreeMem(){
  if(xmem && pxs){
   if(pxs!=pBufMem) delete[] pxs;
   pxs=0;
  }
  xmem= 0;
 };
 void Clear(){
  FreeMem();
  xnum=0;
 };
 
 //EnsureMem: 保证拥有指定数量的内存, 使用 ReallocMem !
 bool EnsureMem(int mem){
  if(mem>xmem){
   return ReallocMem(mem, true);
  }
  return true;
 };

protected:
 //virtual? ReallocMem: 使用 memcpy, memset !
 bool ReallocMem(int mem, bool freeMem){
  ASSERT(!IsTmpObj()); //临时对象不允许写操作!
  if(mem<4)//自动执行内存增长
   mem= AddMemAuto();
  X *pNew= new X[mem];
 // TRACE("XList::ReallocMem pNew = 0x%08x\n",pNew);
  if(pNew==0){
   TRACE("XList::ReallocMem() failed!\n");
   return false;
  }

  if(pxs){
   if(xnum>0)
    memcpy(pNew, pxs, sizeof(X)*xnum);
   if(freeMem && xmem){
    memset(pxs, 0, sizeof(X)*xnum);
    if(pxs!=pBufMem) delete[] pxs;
   }
  }
  pxs= pNew;
  xmem= mem;
  return true;
 }; 

public:
 void Init0(){
  xmem= 0;
  xnum= 0;
  pxs= 0;
 };
 bool IsNull() const{
  return (pxs==0 || xnum==0);
 };
 bool IsValid() const{
  return (pxs && xnum>0);
 };
 
 int Add(const X& x){//quick add(拷贝对象)不检查内存
  ASSERT(xnum<xmem);
  pxs[xnum++]= x;
  return 1;
 };
 int AddEx(X& x){//quick add(转移对象)不检查内存
  ASSERT(xnum<xmem);
  memcpy(pxs+xnum, &x, sizeof(X));
  memset(&x, 0, sizeof(X));
  ++xnum;
  return 1;
 };

 int AddOne(const X& x){ //拷贝对象:使用 operator=
  if(xnum==xmem){
   X* pold= pxs; //考虑 AddOne(pxs[0])!
   if(!ReallocMem(0, false))
    return 0;
   pxs[xnum]= x;
   if(pold){
    memset(pold, 0, sizeof(X)*xnum);
    if(pold!=pBufMem) delete[] pold;
   }
   ++xnum;
  }
  else
   pxs[xnum++]= x;
  return 1;
 };
 int AddOneEx(X& x){//转移对象:使用 memcpy, memset
  if(xnum==xmem){
   X* pold= pxs; //考虑 AddOne(pxs[0])!
   if(!ReallocMem(0, false))
    return 0;
   memcpy(pxs+xnum, &x, sizeof(X));   
   if(pold){
    memset(pold, 0, sizeof(X)*xnum);
    if(pold!=pBufMem) delete[] pold;
   }
  }
  else
   memcpy(pxs+xnum, &x, sizeof(X));
  memset(&x, 0, sizeof(X));
  ++xnum;
  return 1;
 };

 //检查是否已经有相同的元素
 int AddOneNoEqual(const X& x){
  for(int k=0; k<xnum; k++){
   if(pxs[k]==x)
    return 0;
  }
  AddOne(x);
  return 1;
 };

 void operator+= (const XList<X>& lst){
  if(lst.IsValid()){
   ASSERT(lst.pxs!=pxs);
   EnsureMem(xnum+lst.xnum);
   memcpy(pxs+xnum, lst.pxs, sizeof(X)*lst.xnum);
   xnum+= lst.xnum;
  }
 };

 //注意: 两种形式的operator[]
 //为方便使用而提供的, 建议直接使用指针pxs!
 X& operator []( int k ){//用法: XList[k]= x;
  ASSERT(pxs);
  return pxs[k];
 };
 const X& operator []( int k ) const{//用法: x= XList[k];
  ASSERT(pxs);
  return pxs[k];
 };
 const X& Last() const{
  ASSERT(pxs);
  return pxs[xnum-1];
 };

 void Revert(){
  const int H= (xnum>>1);
  int k,n= xnum-1;
  X t;
  for(k=0; k<H; k++){
   t= pxs[k];
   pxs[k]= pxs[n];
   pxs[n--]= t;
  }
 };

protected:
 //自动内存增长策略
 int AddMemAuto() const{
  int add;
  if(xmem<64)//倍增
   add= max(4, xmem);
  else//半增
   add= (xmem>>1);
  return (xmem+add);
 };

 void InitFrom(const XList& r){
  xmem= r.xmem;
  xnum= r.xnum;
  if(xmem>0){
   pxs= new X[xmem];
  // TRACE("pxs = 0x%08x\n",pxs);
  }
  else
   pxs= 0;
  if(xnum>0){
  // memcpy(pxs, r.pxs, sizeof(X)*xnum);
   for(int k=0; k<xnum; ++k)
    pxs[k]= r.pxs[k];
  }
 };
};


//XListEx: use TransTo in ReallocMem!
template <typename X>
class XListEx: public XList<X>
{
public:
 XListEx(int xm=0):XList<X>(xm){};
 ~XListEx(){};

 XListEx(const XListEx& r){
  InitFrom(r);
 };
 void operator=(const XListEx& r){
  if(pxs){
   if(pxs!=pBufMem) delete[] pxs;
   pxs=0;
  }
  InitFrom(r);
 };

protected:
 //virtual? ReallocMem: 不使用 memcpy, memset,而是使用 TransTo !
 bool ReallocMem(int mem, bool freeMem){
  ASSERT(!IsTmpObj()); //临时对象不允许写操作!
  if(mem<4)
   mem= AddMemAuto();
  X *pNew= new X[mem];
 // TRACE("XListEx::ReallocMem: pNew = 0x%08x\n",pNew);
  if(pNew==0){
   TRACE("XListEx::ReallocMem() failed!\n");
   return false;
  }

  if(pxs){
   if(xnum>0){  
    for(int k=0; k<xnum; k++)
     pxs[k].TransTo(pNew[k]);
   }
   if(freeMem && xmem){
    if(pxs!=pBufMem) delete[] pxs;
   }
  }
  pxs= pNew;
  xmem= mem;
  return true;
 };

public:
 //不提供实现,屏蔽掉这两个基类成员函数!
 int Add(const X& x);
 int AddOne(const X& x);
 void operator+= (const XListEx<X>& lst);

 int AddEx(X& x){//quick add, 不检查内存
  ASSERT(xnum<xmem);
  x.TransTo(pxs[xnum]);
  ++xnum;
  return 1;
 };
 int AddOneEx(X& x){
  if(xnum==xmem){
   X* pold= pxs;
   if(!ReallocMem(0, false))
    return 0;
   x.TransTo(pxs[xnum]);
   if(pold){
    if(pold!=pBufMem) delete[] pold;
   }
  }
  else
   x.TransTo(pxs[xnum]);
  ++xnum;
  return 1;
 };

 void Revert(){
  const int H= (xnum>>1);
  int k,n= xnum-1;
  X t;
  for(k=0; k<H; k++){
   pxs[k].TransTo(t);
   pxs[n].TransTo(pxs[k]);
   t.TransTo(pxs[n]);
   --n;
  }
 }
};


//XList11: using operator=, 一个一个的copy in ReallocMem!
template <typename X>
class XList11: public XList<X>
{
public:
 XList11(int xm=0):XList<X>(xm){};
 ~XList11(){};

 XList11(const XList11& r){
  InitFrom(r);
 };
 void operator=(const XList11& r){
  if(pxs){
   if(pxs!=pBufMem) delete[] pxs;
   pxs=0;
  }
  InitFrom(r);
 };

protected:
 //virtual? ReallocMem: 使用 operator= !
 bool ReallocMem(int mem, bool freeMem){
  ASSERT(!IsTmpObj()); //临时对象不允许写操作!
  if(mem<4)
   mem= AddMemAuto();
  X *pNew=new X[mem];
 // TRACE("XList11::ReallocMem pNew = 0x%08x\n",pNew);
  if(pNew==0){
   TRACE("XList11::ReallocMem() failed!\n");
   return false;
  }

  if(pxs){
   for(int k=0; k<xnum; ++k)
    pNew[k]= pxs[k];
   if(freeMem && xmem){
    if(pxs!=pBufMem) delete[] pxs;
   }
  }
  pxs= pNew;
  xmem= mem;
  return true;
 };

public:
 int AddEx(X& x){//quick add, 不检查内存
  Add(x);
  return 1;
 };
 int AddOneEx(X& x){
  AddOne(x);
  return 1;
 };

 void operator+= (const XList11<X>& lst){
  if(lst.IsValid()){
   EnsureMem(xnum+lst.xnum);
   for(int k=0; k<lst.xnum; ++k)
    pxs[xnum++]= lst.pxs[k];
  }
 };
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值