1. Vector 概念
作为STL中常用的序列式容器,vector的数据安排与操作方式,与array都十分相似,它们唯一的差别是对于空间运用的灵活性。array称为静态数组,一旦初始化则不能改变大小,而vector称为动态数组,随着元素的不断加入,它的内部机制会自行扩充空间。因此,vector的实现技术,关键在于其对空间大小的控制以及重新配置时的数据移动效率。
2. Vector 定义
为了简单起见,Vector底层实现代码中均省略空间配置器等接口的描述。Vector底层所采用的数据结构非常简单:线性连续空间,并且运用三个指针进行一系列操作。
如下图所示,Vector新增元素时,如果超过当时的容量,则容量会扩充至两倍或者更大空间(重新配置、移动数据、释放原空间)。
2.1. Vector嵌套型别定义
typedef T value_type; // 泛型定义
typedef value_type* pointer; // 原生指针
typedef value_type* iterator; // 迭代器
typedef value_type& reference; // 原生引用
typedef size_t size_type; // 容器unsigned类型
typedef ptrdiff_t different_type; // 容器signed类型
2.2. Vector 成员变量
iterator start; // 表示目前使用空间的头
iterator finish; // 表示目前使用空间的尾
iterator end_of_storage; // 表示目前可用空间的尾
2.3. Vector 构造函数
vector() : start(0),finish(0),end_of_storage(0) {}
vector(size_type n, const T& value)
{
start = allocate_and_fill(n, value); //申请一段连续内存地址,并填充n个value值
finish = start + n;
end_of_storage = finish;
}
vector(int n, const T& value)
{
start = allocate_and_fill(n, value);
finish = start + n;
end_of_storage = finish;
}
vector(long n, const T& value)
{
start = allocate_and_fill(n, value);
finish = start + n;
end_of_storage = finish;
}
explicit vector(size_type n)
{
start = allocate_and_fill(n, T()); //explicit关键字的作用就是防止类构造函数的隐式自动转换.
finish = start + n;
end_of_storage = finish;
}
2.4. Vector 常用函数
iterator begin()
{
return start;
}
iterator end()
{
return finish;
}
iterator size()
{
return size_type(end()-begin());
}
size_type capacity()
{
return size_type(end_of_storage - begin());
}
bool empty()
{
return begin() == end();
}
reference operator[](size_type n)
{
return *(begin()+n);
}
reference front()
{
return *begin();
}
reference back()
{
return *(end()-1);
}
reference push_back(const T& x)
{
if (finish != end_of_storage) { // 如果内存足够
construct(finish,x); //在finish所指之处产生x的复制品
++finish;
} else {
insert_aux(end(),x); //在end()后新增x
}
}
void push_back()
{
--finish;
destory(finish); //摧毁finish
}
iterator erase(iterator position)
{
if (position+1 != end())
copy(position+1,finish,position); //后续元素往前移动
--finish;
destroy(finish);
return position;
}
void resize(size_type new_size, const T& x)
{
if (new_size < size())
erase(begin()+new_size,end());
else
insert(end(),new_size-size(),x);
}
void resize(size_type new_size)
{
resize(new_size,T());
}
void clear()
{
erase(begin(),end());
}
值得一提的是,所谓动态增加大小,并不是在原空间之后接续新空间,因为无法保证原空间之后尚有可供配置的空间,而是以原大小的两倍或者更大配置一块较大空间,然后将原内容拷贝过来,最后才开始在原内容之后构造新元素,并释放原空间。
因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器将全部失效。