模板类vector是数组的替代品,它是一种动态数组,在内部自动使用new和delete来管理内存(所以也是自由存储区)。
- 与其他标准的顺序容器相比,vector能更有效访问容器内的元素和在末尾添加和删除元素;而在其他位置添加和删除元素,vector则不及其他顺序容器,在迭代器和引用也不比list支持的好。
- 容器的大小和容器的容量是有区别的:大小是指元素的个数,容量是分配的内存大小,容量一般不小于容器的大小。vector::size()返回容器的大小,vector::capacity()返回容量值。
1. vector的遍历
vector<int> vec
的遍历方式有:
for(int i=0; i<a.size(); i++)
for(iter=vec.begin(); iter!=vec.end();iter++)
for_each( , , );
2. vector的查找
vector<int> vec(5)
的查找方式为find:
#include<algorithm>
...
vector<int>::iterator iter = find(vec.begin(), vec.end(), 3);
找到返回第一次出现位置迭代器,找不到返回vec.end()
。
find函数不属于vector的成员,而存在于算法中,所以应加上头文件<algorithm>。
3. vector的删除
vector的删除有erase和pop_back函数。erase可以删除指定元素或指定位置的元素,而pop_back只能去掉数组的最后一个数据。
for(vector<int>::iterator iter=vec.begin(); iter!=end(); )
{
if(*iter==3)
iter = vec.erase(iter);
else
++iter;
}
上述删除vec中值为3的元素。
条件语句里面删除元素时,iter = vec.erase(iter);
返回值指向已删除元素的下一位置,不是删除元素时则直接进行++操作。
而语句vec.erase(vec.begin()+i, vec.begin()+j)
则删除区间[i,j)间的元素。
4. vector的增加
vector的增加有insert和push_back两种方式。insert是插入元素到某个位置中,push_back是在最后添加一个元素。
iterator insert(iterator loc, const TYPE &val);
//在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器
void insert(iterator loc, size_type num, const TYPE & val);
//在指定位置loc前插入num个值为val的元素
void insert(iterator loc, input_iterator start, input_iterator end);
//在指定位置loc前插入区间[start,end)的元素
5. vector的内存管理与效率
vector容器支持随机访问,为了提高效率采用的是动态数组的方式实现。当进行insert或push_back增加元素的操作时,如果此时动态数组的内存不够用,就要动态的重新分配当前大小的1.5~2倍的新内存区,再把原数组的内容复制进去。所以在一般情况下,其访问速度同一般数组相比,只有在需要重新分配内存时,其性能才会下降。
总结: 对于vector容器,如果有大量数据需要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现许多次容量扩充操作,导致效率低下。
6. resize()与reserve()
-
resize(n):强制把容器改为容纳n个元素,如果n小于当前大小,容器尾部的元素会被销毁。
-
reserve(n):把容器容量改为不小于n,如果n小于当前容量,vector会忽略它。
-
通常有两种情况使用reserve来避免不必要的重新分配:
- 当知道有多少元素将最后出现在容器中时,可以提前reserve适当数量的空间;
- 保留可能需要的最大空间,然后添加完全部数据后,再修饰掉任何多余的容量。
7. 通过swap修整vector过剩空间或释放vector全部内存
-
修整过剩内存:
采用“收缩到合适”的方法,只需要一条语句:vector<int>(vec).swap(vec);
表达式vector<int>(vec)表示通过拷贝构造函数建立一个临时vector,它只分配拷贝的元素需要的内存,所以这个临时vector没有多余的容量。然后,临时vector和vec交换数据,使得vec中只有临时变量修正过的容量,临时vector则在语句结束时被销毁。 -
释放所有内存:
vector<int>().swap(vec);
或者:vec.swap(vector<int>());
思想与1相同,只是使用默认构造函数建立一个空的临时vector与原来的vec交换。