对于vector和string来说,当它们的需要更多空间时,就会自动增加空间,而每次增加空间的容量会导致很大的开销,首先必须分配新的内存块,它有容器目前容量的几倍(在大部分实现中,vector和string的容量每次变为2倍),然后把所有元素从容器的旧内存拷贝到它的新内存,接着销毁旧内存中的对象,最后回收旧内存。
看到以上的那些步骤,我不禁对容器自动扩大空间的性能感到担忧,不仅如此,每次重新分配空间,所有指向vector或string中的迭代器、指针和引用都会失效,这意味着简单地把一个元素插入vector或string的动作也可能需要更新其他使用了指向vector或string中的迭代器、指针或引用的数据结构而膨胀。
例如,假定你想建立一个容纳1-1000值的vector<int>。没有使用reserve,你可以像这样来做:
vector<int> v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);
在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。(10这个数没什么奇怪的。记住vector在重新分配发生时一般把容量翻倍,而1000约等于2的10次方。)
所以,在可以提前可以预知需要存储元素数量的情况下,可以这样做,
vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);
这样循环中不会发生重新分配。
代码示例:
//reserve
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> coll,coll1(80);
coll.reserve(80);
//测试预置空间大小
cout<<"coll: ";
cout<<"size: "<<coll.size()<<", capacity: "<<coll.capacity()<<endl;
cout<<"coll1: ";
cout<<"size: "<<coll.size()<<", capacity: "<<coll.capacity()<<endl;
for(int i=0;i<100;i++)
{
coll.push_back(i);//只有当容器内的元素容量大于预置容器容量时,才重新分配内存
}
cout<<"size:"<<coll.size()<<",capacity:"<<coll.capacity()<<endl;
for(int i=0;i<100;i++)
{
coll1.push_back(i);只有当容器内的元素容量大于预置容器容量时,才重新分配内存
}
cout<<"size:"<<coll.size()<<",capacity:"<<coll.capacity()<<endl;
system("pause");
return 0;
}
以上代码中,起码前0-79个元素插入到容器,是没有进行重新分配的,如果能够预估数量,就可以最大可能的减少重新分配,保证高效的插入元素。
但是要注意,如果容器中reserve的容量太大,而实际中根本不需要那么多,或者元素插入完成后,以后就不会再进行插入操作了,那么多出来的这部分空间就是过剩空间,而对于过剩空间,我们可以通过“交换技术”成功缩小空间,交换技巧的变体可以用于清除容器和减少它的容量到你的实现提供的最小值。
代码示例:
//缩减过剩空间
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
template<class T>
class f
{
T value;
public:
f(T ivalue):value(ivalue){}
~f(){}
bool operator()(const int& elem) const
{
return elem<value;
}
};
int main()
{
vector<int> coll;
vector<int>::iterator pos;
for(int i=0;i<100;i++)
{
coll.push_back(i);
}
cout<<"size:"<<coll.size()<<",capacity:"<<coll.capacity()<<endl;
coll.erase(remove_if(coll.begin(),coll.end(),f<int>(90)),coll.end());
cout<<"size:"<<coll.size()<<",capacity:"<<coll.capacity()<<endl;
vector<int>(coll).swap(coll);//关键部分
cout<<"size:"<<coll.size()<<",capacity:"<<coll.capacity()<<endl;
system("pause");
return 0;
}