Vector向量容器相当于一个动态的数组,当向向量容器中不断加入元素,若超过容器本身的大小限制,vector会自动拓展大小,在这过程中涉及到内存的分配和回收。vector中有size()capacity()函数,与之相对应的两个函数resize(size_type)reserve(size_type)Size函数是指返回当前容器中的元素个数,对应的resize(size_type)会在容器尾添加或删除一些元素,来调整容器中实际的内容,使容器达到指定的大小。Capacity指最少要多少元素才会使其容量重新分配,对应reserve(size_type new_size)会置这个capacity值,使它不小于所指定的new_size。有了这两个函数,可以通过下面的代码来测试一下,缺省情况下Vector的扩展机制是怎样。

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

int main()
{
	vector<int> v;
	vector<int>::size_type tmp = 0;
	ofstream ofs("resize.txt");
	for (int i = 0, j = 1; i < 10000000; i++)
	{
		v.push_back(i);
		if (v.capacity() != tmp)
		{
			cout << j << " " << v.capacity() << endl;
			ofs << j << " " << v.capacity() << endl;
			tmp = v.capacity();
			j++;
		}
	}
	return 0;
}
执行的结果如下:

从第二例数据可以看出,缺省情况下vector的扩展机制是按2倍拓展的也就是指数递增。在整个大小拓展的过程中,主要的步骤如下:

1)为需要的新容量分配足够的内存;

2)将元素从原来的内存拷贝到新内存中;

3)销毁原来内存中的元素;

4)归还原来的内存。   

如果元素的数目为n,那么我们知道步骤(2)(3)都要占用O(n)的时间,除非分配或归还内存的代价的增长超过O(n),否则这两步将在全部运行时间中占居支配地位。因此我们可以得出结论:无论用于重新分配的容量(capacity)是多少,重新分配一个 大小(size)为nvector需要占用O(n)的时间。这个结论暗示了一种折衷权衡。假如在重新分配时请求大量的额外内存,那么在相当长的时间内将无需再次进行重新分配,因此总体重新分配操作消耗的时间相对较少,这种策略的代价在于将会浪费大量的空间。另一方面,我们可以只请求一点点额外的内存,这么做将会节约空间,但后继的重新分配操作将会耗费时间。换句话说,我们面临一个经典的抉择:拿时间换空间,或者拿空间换时间。当然在ACM题目的解答过程中,一般会告知数据的范围,这样我们可以定义vector容器的大小,即使没有告知数据量的大小,但是一定要避免陷入vector容器自增长造成内存空间的浪费。当然,当vector容量不够用的时候我们可以根据需要定义需要拓展的大小。

#include <iostream>
#include <vector>
using namespace std;

void showInfo(vector<int> &v)
{
	int i;
	for(i=0;i<v.size();i++)
		cout<<v[i]<<" ";
	cout<<endl;
}

int main()
{
	vector<int> v;
	int i;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	//此时v的实际大小
	cout<<"size="<<v.size()<<endl;
	showInfo(v);
	//根据需要拓展大小
	v.resize(10);
	v.insert(v.begin()+4,5);
	cout<<"size="<<v.size()<<endl;
	showInfo(v);
	return 0;
}

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐