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

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

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

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

先看个例子

  1. vector<int> vec;
  2. for(int i = 0; i < 10; i++)
  3. {
  4. vec.push_back(i)
  5. }

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

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

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

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

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

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

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

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

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

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

  1. vector<int> vec;
  2. vec.reserve(15);
  3. for(int i = 0; i < 10; i++)
  4. {
  5. vec.push_back(i)
  6. }

这个过程在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. Just a Hook(树状数组)

    In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. T ...

  2. 分布式系统CAP定理

    分布式系统领域有个著名的CAP定理: C-数据一致性: A-服务可用性: P-服务对网络分区故障的容错性 这三个特性在任何分布式系统中不能同时满足,最多同时满足两个 ZooKeeper是个CP的,即任 ...

  3. 对get post请求的封装

    HttpUtil.java package com.dhc.task.wx.util; import java.io.BufferedReader; import java.io.IOExceptio ...

  4. 为cscope查找列表增添色彩

    我在使用cscope的时候,偏好于不用quickfix窗口来显示查找列表,而是选择类似ctag的列表.但这会带来一个比较麻烦的问题,就是窗口列表一片白色,看起来非常难受: 特别是当搜索结果特别多的时候 ...

  5. quartz在web.xml的配置

    第一步:下载所需的Jar包 commons-beanutils.ja.commons-collections.jar.commons-logging.jar.commons-digester.jar. ...

  6. linux单用户模式修改密码

    Linux使用版本: Centos 7 救援模式: 1,在虚拟机设置里查看光驱是否开启启动,要保证设置状态里的两个选项都已选择. 2,先将Centos系统关机,然后在VMware左侧选中这台虚拟机并右 ...

  7. 学习神器!本机安装虚拟机,并安装Linux系统,并部署整套web系统手册(包含自动部署应用脚本,JDK,tomcat,TortoiseSVN,Mysql,maven等软件)

    1.   引言 编写目的 本文档的编写目的主要是在Linux系统上部署mis_v3员工管理系统,方便测试,并为以后开发人员进行项目部署提供参考 准备工作 软件部分 软件项 版本 备注 Mysql 5. ...

  8. Python代码注释

    1.单行注释使用# # Code 2.多行注释,成对使用'''或""",三个单撇号或三个双引号 “”” Code “”” 3.多行快捷注释 1).增加注释 选中待注释的多 ...

  9. 面试题:Java必知必会:异常机制详解 背1

    一.Java异常概述 在Java中,所有的事件都能由类描述,Java中的异常就是由java.lang包下的异常类描述的. Trowable是所有异常的超类.  他的常用方法printStackTrec ...

  10. Solidity 合约调用合约

    原文地址:https://medium.com/@k3no/making-a-birthday-contract-858fd3f63618 先将datetime合约部署:https://github. ...