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

(1)分配内存步骤

关于STL,它们会自动增长以便容纳下你放入的数据,只要没有超出它们的最大限制就可以。对于vector和string,如果需要更多空间,就以类似realloc的思想来增长大小。这个类似于realloc的操作有四个部分:

**1. 分配新的内存块,分配的大小一般为当前容器内存的倍数。在大部分实现中,vector和string的容量每次以2的倍数为增长。即,当容器必须扩展时,它们的容量每次翻倍。
2. 把所有元素从容器的旧内存拷贝到它的新内存。
3. 析构旧内存中的对象
4. 释放旧内存**

考虑到以上所有的分配,复制,析构和释放,你就应该知道那些步骤都很昂贵。当然,你不会想要比必须的更为频繁地执行它们。如果这没有给你打击,那么也许当你想到每次这些步骤发生时,所有指向vector或string中的迭代器、指针和引用都会失效时,它会给你打击的。这意味着简单地把一个元素插入vector或string的动作,也可能因为需要更新其他使用了指向vector或string中的迭代器、指针或引用

reserve成员函数能使你把重新分配的次数减少到最低限度,从而避免了重新分配和指针、迭代器、引用失效带来的开销

(2)相关函数分析

  1. size()告诉你容器中有多少元素。它没有告诉你容器为它容纳的元素分配了多少内存。
  2. capacity()告诉你容器在它已经分配的内存中可以容纳多少元素。那是容器在那块内存中总共可以容纳多少元素,而不是还可以容纳多少元素。如果你想知道一个vector或string中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发上面的重新分配步骤。
  3. resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。
  4. reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。在我的经验中,使用reserve来从一个string中修整多余容量一般不如使用“交换技巧”,那是条款17的主题。)

(3)使用reserve()函数预分配

假定你想建立一个容纳1-1000值的vector。没有使用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);

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值