STL有现成的,为什么要重新制造呢?为了锻炼自己,看看自己对底层了解到什么程度。话说前头,我可没有去研究过STL的源码,本人实力有限,看那玩意儿太恶心。vector——数组,我最熟悉的容器,在我看来是最容易实现的,所以从它开始。
vec类的声明
template<class type>
class vec
{
public:
vec();//默认构造函数
vec(unsigned int size,const type& data);//初始化构造函数
vec(const vec& copy);//拷贝构造函数
virtual ~vec();//析构函数
public:
unsigned int size();//返回vec的元素数量
void push_back(const type& data);//从vec最后面插入一个新元素
void pop_back();//将vec最后一个元素删除 并且释放掉它的内存空间
type& operator[](unsigned int i);//重载[] 然后可以用下标操作vec
public:
typedef type* iter;//迭代器
iter begin()//返回指向首元素的迭代器
{
it=_begin;
return it;
}
iter end()//返回指向末尾元素的迭代器
{
it=_begin+_size;
return it;
}
iter operator++()//重载++符号 用于操作迭代器
{
it=it+1;
}
private:
type* _begin;//vec的首地址
unsigned int _size;//数组元素个数
iter it;//迭代器
};
下面是各个接口的实现,顺便提一下为什么很多函数的形参用的是const修饰加变量引用。因为type可能是一个类,变量引用可以避免重新构造一个对象,浪费空间。
const修饰是为了避免常量作为函数实参时报错。并不是加了const就意味着实参必须是常量,这个是我之前的误解。但是加了const意味着这个参数只能用于输入。
template<class type>
vec<type>::vec()
{
_begin=NULL;
_size=0;
}
template<class type>
vec<type>::vec(unsigned int size,const type& data)//插入size个元素,每个元素的值为data
{
_size=size;
_begin=NULL;
_begin=(type*)malloc(sizeof(type)*size);//这里暂时用C语言的手动分配堆空间的函数 后面可能会自己设计一个内存池接口,取代它
if(_begin!=NULL)//分配内存失败时,返回空指针,需要做异常处理
{
for(unsigned int i=0;i<size;i++)
{
_begin[i]=data;
}
}
else
{
cout<<"vec init error!"<<endl;//
}
}
template<class type>
vec<type>::vec(const vec& copy)//拷贝构造函数 这里形参必须是引用变量 否则会无限构造对象 死循环
{
this->_size=copy->_size;
this->_begin=copy->_begin;
}
template<class type>
vec<type>::~vec()//释放_begin指向的内存空间
{
free(_begin);
}
template<class type>
unsigned int vec<type>::size()
{
return _size;
}
template<class type>
void vec<type>::push_back(const type& data)
{
_size++;//数组元素个数+1
_begin=(type*)realloc(_begin,_size*sizeof(type));//数组大小变了 这里要重新分配内存空间
if(_begin!=NULL)//分配内存失败需要异常处理
{
_begin[_size-1]=data;
}
else
{
cout<<"push_back error!"<<endl;
}
}
template<class type>
void vec<type>::pop_back()
{
_size--;
_begin=(type*)realloc(_begin,_size*sizeof(type));
if(_begin==NULL)
{
cout<<"pop_back error!"<<endl;
}
}
template<class type>
type& vec<type>::operator[](unsigned int i)//返回引用变量是为了让它可以成为‘=’的左操作数,即可以用下标操作,改变元素的值
{
if(i<_size && i>=0)//要防止下标越界
{
type& tmp=_begin[i];
return tmp;
}
else
{
type& tmp=_begin[0];
cout<<"operator++ error!"<<endl;
return tmp;
}
}
//下面是测试用的main函数 常规操作已经实现 但是定义二维数组会有问题 比如vec<vec<int>> ,会达不到想要的效果
int main()
{
vec<int> me(5,2);
cout<<"first test:"<<endl;
for(vec<int>::iter i=me.begin();i!=me.end();i++)//用迭代器遍历
{
cout<<(*i)<<endl;
}
cout<<"second test:"<<endl;
me.push_back(4);
for(int i=0;i<me.size();i++)//用下标遍历
{
cout<<me[i]<<endl;
}
cout<<"third test:"<<endl;
me.pop_back();
me[1]=6;
for(vec<int>::iter i=me.begin();i!=me.end();i++)
{
cout<<(*i)<<endl;
}
system("pause");
return 0;
}