在用模板创建顺序表的时候,每一次插入之前我们都会进行判断容器是否已满的操作,于是就封装了一个函数,用来专门进行扩容操作,具体如下所示:

void CheckCapacity()

{

  if(_size==_Capacity)

  {

   T* tmp=new T [2*_Capacity+3];

   memcpy(tmp,_data,_size*sizeof(T));

   delete [] _data;

   _data=tmp;

   _Capacity=2*_Capacity+3;

  }

}


    其实对于这个函数从在一定的问题,就是浅拷贝!!!当我们在顺序表里插入字符串的时候不难发现当插入字符超过一定的限度时程序会出现问题,究竟是为何呢?(今天不知道怎么地,愣是传不了照片,不然在这里用图片描述会更为清晰的哦!)

    原因是string里边有一个相当于数组一样的东西bufr,它的大小为16个字节,当我们在进行扩容的时候,如果要插入的内容大于bufr所指向数组的大小,则由string里边的指针ptr指向,所以在在扩容完成之后进行拷贝的时候,指向原来内存的指针和拷贝完成后的指针指向了同一块空间,在对象析构的时候被释放了两次。这样的结果无疑会造成程序崩溃。

   鉴于上述现象,我们对扩容函数进行的改造:

void CheckCapacity()

{

if(_size==_capacity)

{

int i=0;

for(i=0;i<_size;i++)

{

tmp[i]=_data[i];

}

delete [] _data;

  _data=tmp;

  _Capacity=2*_Capacity+3;

}

}

  这个函数虽然解决了浅拷贝的问题,但不是最理想的结果,如果有一种方法能够让我们在扩容的时候就知道数据是内置类型还是非内置类型,如果是内置类型,我们直接进行memcpy如果是非内置类型,在用循环语句进行挨个拷贝,这样程序的性能岂不是会提高很多呢?

    类型萃取方法就能很好的解决这个问题,类型萃取(抽取)技术就是要抽取类型的一些具体特征(trait),比如它是哪种具体类型,它是引用类型,内建类型,还是类类型等。可见,类型萃取技术其实就是trait模板技术的具体体现。实现类型萃取要用到的基本思想一个是特化,一个就是用typedef来携带类型信息。实际上,我们在用模板做设计时,一般建议在模板定义内部,为模板的每个类型参数提供typedef定义,这样在泛型代码中可以很容易地访问或抽取这些类型。
     
对于头文件里特化了的类型,我们都可以认为是内置类型,所以在进行扩容的时候通过监视窗口可以发现程序直接跳转到memcpy语句处,对于非特化类型则调转到else语句处,进行逐个拷贝。

void CheckCapacity()

{

/*if(_size==_capacity)

{

int i=0;

for(i=0;i<_size;i++)

{

tmp[i]=_data[i];

}

 delete [] _data;

   _data=tmp;

   _Capacity=2*_Capacity+3;

}

}*/

  if(_size==_Capacity)

  {

   T* tmp=new T [2*_Capacity+3];

   if(Typetraits<T>::isPodType().Get())

   {

cout<<"__TrueType:"<<typeid(T).name()<<endl;

    memcpy(tmp,_data,_size*sizeof(T));

   }

   else

   {

int i=0;

   for(i=0;i<_size;i++)

   {

   tmp[i]=_data[i];

   }

   }

   delete [] _data;

   _data=tmp;

   _Capacity=2*_Capacity+3;

  }

}


源代码

.h

#pragma


struct TrueType

{

bool Get()

{

return true;

}

};

struct FalseType

{

bool Get()

{

return false;

}

};

template <typename T>//内嵌型别

struct Typetraits

{

typedef FalseType isPodType;

};

template <>

struct Typetraits<int>

{

typedef FalseType isPodType;

};

template <>

struct Typetraits<float>

{

typedef FalseType isPodType;

};

template <>

struct Typetraits<char>

{

typedef FalseType isPodType;

};

.cpp

#include<iostream>

#include<string>

#include"类型萃取.h"

using namespace std;

template<typename T>

class Seqlist

{

public:

Seqlist():

_data(NULL)

,_size(0)

,_Capacity(0)

{

CheckCapacity();

}

~Seqlist( )

{

if(_data!=NULL)

{

delete [] _data;

    }

}

//

void CheckCapacity()

{

/*if(_size==_capacity)

{

int i=0;

for(i=0;i<_size;i++)

{

tmp[i]=_data[i];

}

delete [] _data;

  _data=tmp;

  _Capacity=2*_Capacity+3;

}

}*/

 if(_size==_Capacity)

 {

  T* tmp=new T [2*_Capacity+3];

  if(Typetraits<T>::isPodType().Get())

  {

cout<<"__TrueType:"<<typeid(T).name()<<endl;

   memcpy(tmp,_data,_size*sizeof(T));

  }

  else

  {

int i=0;

  for(i=0;i<_size;i++)

  {

  tmp[i]=_data[i];

  }

  }

  delete [] _data;

  _data=tmp;

  _Capacity=2*_Capacity+3;

 }

}

Seqlist(const Seqlist& s)

:_data(s._data)

,_size(s._size)

,_Capacity(s._Capacity)

{

 _data=new T [s._Capacity];

 memcpy(_data,s._data,_size*sizeof(T))

}

void display()

{

int i=0;

for(i=0;i<_size;i++)

{

cout<<_data[i]<<" ";

}

cout<<endl;

}

void PushBack(const T &p);

void PopBack();

void PushFront(const T &p);

void PopFront();

void Insert(Seqlist&s,int pos ,const T &p);

void Sort();

private:

T* _data;

int _size;

int _Capacity;

};

template<typename T>

void Seqlist<T>::PushBack(const T &p)

{

CheckCapacity();

_data[_size]=p;

_size++;

}

template<typename T>

void Seqlist<T>::PopBack()

{

if(_size<=0)

{

cout<<"顺序表为空"<<endl;

return;

}

--_size;

}

template<typename T>

void Seqlist<T>::PushFront(const T &p)

{

    CheckCapacity();

int start=_size-1;

    while(start>=0)

 {

 _data[start+1]=_data[start];

 start--;

 }

 _data[0]=p;

_size++;

}

template<typename T>

void Seqlist<T>::PopFront()

{

if(_size<=0)

{

cout<<"顺序表为空"<<endl;

}

else

{

int i=0;

for(i=0;i<_size;i++)

{

_data[i]=_data[i+1];


}

--_size;

}

}

template<typename T>

void Seqlist<T>::Insert(Seqlist&s,int pos ,const T &p)

{

int i=0;

CheckCapacity();

for(i=_size;i>pos;i--)

{

_data[i]=_data[i-1];

}

_data[pos]=p;

++_size;

}

template<typename T>

void Seqlist<T>::Sort()

{

int i=0,j=0;

for(i=0;i<_size-1;i++)

{

for(j=0;j<_size-1-i;j++)

{

if(_data[j]>_data[j+1])

{

T tmp=_data[j];

_data[j]=_data[j+1];

_data[j+1]=tmp;

}

}

}


}

void test1()

{

Seqlist<string> seqlist1;

    seqlist1.PushBack("1111");

seqlist1.PushBack("2222");

seqlist1.PushBack("3333");

seqlist1.PushBack("4444");

seqlist1.PushBack("5555");

seqlist1.PushBack("6666");

//seqlist1.PopBack();

seqlist1.display();

}

void test2()

{

Seqlist<float> seqlist1;

    seqlist1.PushFront(1.0);

seqlist1.PushFront(2.0);

seqlist1.PushFront(3.0);

seqlist1.PushFront(4.0);

seqlist1.PopFront();

seqlist1.Sort();

seqlist1.display();

}

int main ()

{

test1();

   system("pause");

   return 0;

}