vector应该是最常用的容器之一了,它和数组一样,需要维护一个连续的存储空间,但与数组不同的是,vector在空间运用上更灵活,其内部实现已经封装了对存储空间的分配以及对数据元素的操作,用户只需要调用相应的接口就可以实现一般的操作。vector实现技术的关键在于对空间大小的控制以及重新配置时的数据移动的效率。虽然相对数组来说vector操作更加灵活,但是由于其存储特性,在其内部实现中仍然像数组一样逃离不了配置新空间、数据移动、释放旧空间几个基本步骤。
1、在vector的定义中,有3个迭代器成员变量比较重要:
iterator start; //表示目前使用空间的头
iterator finish; //表示目前使用空间的尾
iterator end_of_storage; //表示目前可用空间的尾
vector的几个比较有用的对外接口都是通过这三个指针操作实现的,比如首尾标示、大小、容量、空判断、下标[]运算、最前端元素、最后端元素等,源码如下:
iterator begin()
{
return start;
}
iterator end()
{
return finish;
}
size_type size()const
{
return size_type(end()-begin());
}
size_type capacity()const
{
return size_type(end_of_storage-begin());
}
bool empty()const
{
return begin() = end();
}
reference operator[](size_type n)
{
return *(begin()+n);
}
reference front()
{
return *begin();
}
reference back()
{
return *(end()-1);
}
2、vector的迭代器
vector迭代器的类型其实就是其元素的类型,比如vector<int>::iterator iter; iter的类型其实就是int*,vector<Person>::iterator iter; iter的类型就是Person*。
3、vector的构造函数和内存管理
vector有两个成员函数比较厉害,一个是fill_initialize,另一个是allocate_and_fill,这两个函数都是受保护的,vector的大部分构造函数都是通过这两个函数实现的,函数实现如下:
void fill_initialize(size_type n,const T& value)
{
start = allocate_and_fill(n,value);
finish = start + n;
end_of_storage = finish;
}
iterator allocate_and_fill(size_type n,const T& value)
{
iterator = data_allocator::allocate(n);//空间配置函数
uninitialized_fill_n(result,n,value);//内存处理函数,用于初始化
return result;
}
push_back()的实现:首先检查是否还有备用空间,如果有备用空间,则在目前已使用空间最后添加新的元素;否则则需要配置新的空间,配置的原则是:如果原来的大小为0,则配置1,如果原大小不为0,则配置原来大小的2倍,然后将原来的数据拷贝到新的空间中,最后需要析构并释放原来的vector。