使用reserve来避免不必要的重新分配 分享

来源:互联网 发布:ubuntu安装分区详解 编辑:程序博客网 时间:2024/05/21 22:36
  关于STL容器,只要你不超过它们的最大大小,它们就可以自动增长以满足你的要求。对于vector和string,只要需要更多的空间,就可以用realloc等价思想来增长。这个操作有四个部分。

1.     分配新的内存块,在大部分实现中,vector和string的容量每次以2为因数增长。

2.     把所有元素从容器的就内存拷贝到它新的内存。

3.     销毁就内存中的对象。

4.     回收就内存。

给了所有的分配,回收,拷贝和析构,你就应该知道那些步骤都很昂贵。reserve成员函数允许你最小化必须进行的重新分配的次数,因而可以避免真分配的开销和迭代器/指针/引用失效。

reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。

例如,假定你想建立一个容纳1-1000值的vector<int>。没有使用reserve,你可以像这样来做:

vector<int> v;

for (int i = 1; i <= 1000; ++i) v.push_back(i);

在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。

把代码改为使用reserve,我们得到这个:

vector<int> v;

v.reserve(1000);

for (int i = 1; i <= 1000; ++i) v.push_back(i);

这在循环中不会发生重新分配。

在大小和容量之间的关系让我们可以预言什么时候插入将引起vector或string执行重新分配,而且,可以预言什么时候插入会使指向容器中的迭代器、指针和引用失效。例如,给出这段代码,

string s;

...

if (s.size() < s.capacity()) {

              s.push_back('x');

}

push_back的调用不会使指向这个string中的迭代器、指针或引用失效,因为string的容量保证大于它的大小。如果不是执行push_back,代码在string的任意位置进行一个insert,我们仍然可以保证在插入期间没有发生重新分配,但是,与伴随string插入时迭代器失效的一般规则一致,所有从插入位置到string结尾的迭代器/指针/引用将失效。

通常有两情况使用reserve来避免不必要的重新分配。第一个可用的情况是当你确切或者大约知道有多少元素将最后出现在容器中。那样的话,就像上面的vector代码,你只是提前reserve适当数量的空间。第二种情况是保留你可能需要的最大的空间,然后,一旦你添加完全部数据,修整掉任何多余的容量。


原创粉丝点击