条目十四《使用reserve来避免不必要的重新分配》

使用vector和string的插入元素的时候,我们是不用担心内存问题的(只要不超过容器的max_size)。因为底层有分配子管理内存。在插入元素的时候,内存不够会发生像realloc的过程:

  1. 分配新的内存块,它有容器目前容量的几倍。在大部分实现中,vector和string的容量每次以2为因数增

    长。也就是说,当容器必须扩展时,它们的容量每次翻倍。
  2. 把所有元素从容器的旧内存拷贝到它的新内存。
  3. 销毁旧内存中的对象。
  4. 回收旧内存

先看个例子

vector<int> vec;
for(int i = 0; i < 10; i++)
{
vec.push_back(i)
}

这个过程会发生最少4次重新分配内存的过程。再来看下一个重新分配内存涉及到哪些过程:

  • 1.new操作-->malloc
  • 2.拷贝操作
  • 3.析构对象
  • 4.释放内存

咋一看,一两次还可以接受,当插入的元素越来越多的时候,对性能的消耗是非常客观的。

上面的问题还只是其中一个问题,在插入元素时,重新分配内存会造成迭代器、指针和引用的失效。

为了优化这两个问题,在使用vector和string的时候,可以使用reserve函数。先引出四个关于容器大小和设置的成员函数:

  • size()———————获得容器的元素个数

  • capacity()———获得容器的容量

  • resize()—————强制设置容器的元素个数(参数大于当前大小,调用默认构造函数创建元素填充在尾部。小于当前大小,会析构并销毁多余的元素)

  • reserve()————强制设置容器的容量大小(参数小于现有的容量大小会忽略当前调用,大于会扩容。)

为了避免容器的不必要扩容而造成的消耗,在初始化容器的时候可以通过reserve()设置容器的容量大小,这样在插入元素的是够,只要当前的元素个数小于容量大小,都不会发生重新分配内存。这样也就不会发生迭代器、指针和引用失效等问题,也就没有多次拷贝,析构对象,释放内存的现象发生。

vector<int> vec;
vec.reserve(15);
for(int i = 0; i < 10; i++)
{
vec.push_back(i)
}

这个过程在reserve后插入元素不会发生重新分配内存过程。因为,插入的元素个数(10)小于容量的大小(15)。

可能有人说,在开始时设置过多的容量,那么不就相当于数组吗?浪费了剩余没用到内存,不用担心这个问题,我们可以等插入元素完毕的时候:

  • 调用sesize()来修剪大小
  • 使用swap()技巧。(vector tmp_vec(vec).swap(vec) 利用容器的拷贝构造不会复制空内存的原理,先创建一个纯净的临时容器,然后再交换容器内容,原来的容器就可以成为一个没有多余容量的容器,节省内存哦)

条目十四《使用reserve来避免不必要的重新分配》的更多相关文章

  1. 条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》

    条目二十四<当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择> 当效率至关重要时,应该在map::operator[]和map::insert之 ...

  2. 解剖SQLSERVER 第十四篇 Vardecimals 存储格式揭秘(译)

    解剖SQLSERVER 第十四篇    Vardecimals 存储格式揭秘(译) http://improve.dk/how-are-vardecimals-stored/ 在这篇文章,我将深入研究 ...

  3. 只需十四步:从零开始掌握 Python 机器学习(附资源)

    分享一篇来自机器之心的文章.关于机器学习的起步,讲的还是很清楚的.原文链接在:只需十四步:从零开始掌握Python机器学习(附资源) Python 可以说是现在最流行的机器学习语言,而且你也能在网上找 ...

  4. 条目十五《注意strng实现的多样性》

    条目十五<注意strng实现的多样性> 下面以一个打印string空对象的大小切入本条目: #include #include using namespace std; int main( ...

  5. 只需十四步:从零开始掌握Python机器学习(附资源)

    转载:只需十四步:从零开始掌握Python机器学习(附资源) Python 可以说是现在最流行的机器学习语言,而且你也能在网上找到大量的资源.你现在也在考虑从 Python 入门机器学习吗?本教程或许 ...

  6. Java中的集合(十四) Map的实现类LinkedHashMap

    Java中的集合(十四) Map的实现类LinkedHashMap 一.LinkedHashMap的简介 LinkedHashMap是Map接口的实现类,继承了HashMap,它通过重写父类相关的方法 ...

  7. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  8. 雅虎(yahoo)前端优化十四条军规

    第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ...

  9. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

随机推荐

  1. new Com

    CreateOleObject System.Win.ComObj.hpp #include <objbase.h>     Winapi.ActiveX.pas   CoInitiali ...

  2. Hadoop IO 特性详解(1)

    本文结合hadoop : the definitive guide精心而作,包含作者的心血,希望可以帮助大家理解一点hdfs的皮毛,足矣.(charles@xingbod.cn) hadoop本身自带 ...

  3. $().each和$.each()

    $().each 在dom处理上面用的较多.如果页面有多个input标签类型为checkbox,对于这时用$().each来处理多个checkbook,例如: $(“input[name=’ch’]” ...

  4. 解决mybatis中转义字符的问题

    xml格式中不允许出现类似“>”这样的字符,有如下两种解决方法 方法一:使用转义字符 SELECT * FROM test WHERE 1 = 1 AND start_date <= CU ...

  5. ubuntu 编译并安装resin3.1.12+nginx1.2.6

    一.先装jdk 先建立如下两个目录: mkdir /usr/lib/jvm mkdir /usr/lib/jvm/java 把jdk-6u26-linux-x64.bin文件传到上面目录下: chmo ...

  6. PHP 商城无限极分类

    无限极分类,用的是递归,在外部调用fen()方法即可 index是刚开始寻找的顶级分类,suo是为了在前端展示的时候缩进 ,$suo=){ 一个数组用来返回的 $t=[]; 这是查询数据库的所有内容 ...

  7. 383. Ransom Note 在字典数组中查找笔记数组

    [抄题]: Given an arbitrary ransom note string and another string containing letters from all the magaz ...

  8. 如何从Win7上卸载Sql 2008 R2 Express,再重装

    这两天,因工作需要,需要在一台新的机器上,Win7 64位英文操作系统上,安装Sql Server 2008 R2 Express,安装的过程中出现些问题,在查找问题的过程中,考虑重装 Sql Ser ...

  9. sencha:日期选择组件datepicker

    来源于<sencha touch权威指南> ------------------------------- 除app.js外,其它内容都与上一篇博客里的内容相同.app.js代码如下: E ...

  10. osm2pgsql windows “illegal option -W” error

    新版本不支持 解决: 修改pg_hba.conf的METHOD为trust 参考:http://stackoverflow.com/questions/15510428/osm2pgsql-windo ...