C++ STL vector扩容原理分析
扩容特点:
1)新增元素:vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素;
2)对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 ;
3)初始时刻vector的capacity为0,插入第一个元素后capacity增加为1;
4)不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容。
以成倍方式增长
假定有 n 个元素,倍增因子为 m;

完成这 n 个元素往一个 vector 中的 push_back操作,需要重新分配内存的次数大约为 logm(n);
第 i 次重新分配将会导致复制 m^(i) (也就是当前的vector.size() 大小)个旧空间中元素;
n 次 push_back 操作所花费的时间复制度为O(n):
m / (m - 1),这是一个常量,均摊分析的方法可知,vector 中 push_back 操作的时间复杂度为常量时间。
一次增加固定值大小
假定有 n 个元素,每次增加k个;

第i次增加复制的数量为为:100i
n 次 push_back 操作所花费的时间复杂度为O(n^2):
均摊下来每次push_back 操作的时间复杂度为O(n)。
总结:对比可以发现采用采用成倍方式扩容,可以保证常数的时间复杂度,而增加指定大小的容量只能达到O(n)的时间复杂度,因此,使用成倍的方式扩容。
增长因子的选取:
根据查阅的资料显示,考虑可能产生的堆空间浪费,成倍增长倍数不能太大,使用较为广泛的扩容方式有两种,以2二倍的方式扩容,或者以1.5倍的方式扩容。
以2倍的方式扩容,导致下一次申请的内存必然大于之前分配内存的总和,导致之前分配的内存不能再被使用,所以最好倍增长因子设置为(1,2)之间。
借用一张图来说明2倍与1.5倍的区别:

总结
1)vector在push_back以成倍增长可以在均摊后达到O(1)的事件复杂度,相对于增长指定大小的O(n)时间复杂度更好。
2)为了防止申请内存的浪费,现在使用较多的有2倍与1.5倍的增长方式,而1.5倍的增长方式可以更好的实现对内存的重复利用,因而更好。
C++ STL vector扩容原理分析的更多相关文章
- ArrayList扩容原理分析
1:代码解读和分析 1.1:构造方法分析 1: public ArrayList(int initialCapacity) { ) { this.elementData = new Object[in ...
- ConcurrentHashMap原理分析(二)-扩容
概述 在上一篇文章中介绍了ConcurrentHashMap的存储结构,以及put和get方法,那本篇文章就介绍一下其扩容原理.其实说到扩容,无非就是新建一个数组,然后把旧的数组中的数据拷贝到新的数组 ...
- c++ 从vector扩容看noexcept应用场景
c++11提供了关键字noexcept,用来指明某个函数无法--或不打算--抛出异常: void foo() noexcept; // a function specified as will nev ...
- 「必知必会」最细致的 ArrayList 原理分析
从今天开始也正式开 JDK 原理分析的坑了,其实写源码分析的目的不再是像以前一样搞懂原理,更重要的是看看他们编码风格更进一步体会到他们的设计思想.看源码前先自己实现一个再比对也许会有不一样的收获! ...
- STL vector用法介绍
STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和f ...
- JAVA常用数据结构及原理分析
JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balaba ...
- 转载:solr MoreLikeThis的原理分析
转载地址:http://blog.sina.com.cn/s/blog_5ddc071f0101muos.html 在solr中有两种方式实现MoreLikeThis:MoreLikeThisHand ...
- STL vector 用法介绍
介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...
- STL vector使用方法介绍
介绍 这篇文章的目的是为了介绍std::vector,怎样恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...
随机推荐
- Tomcat启动报错org.apache.catalina.core.StandardContext listenerStart
感谢原文作者:西北码农 原文链接:https://blog.csdn.net/bitree1/article/details/72236633 解决方法: 1.检查配置信息有无异常:如 web.xml ...
- git命令log与reflog的比较
感谢原文作者:杨鲜生 原文链接:https://blog.csdn.net/u013252047/article/details/80230781 用git命令,想看到自己的操作记录,则可以使用log ...
- CAAnimation——简介
- 如何按规定的格式向mysql中导入数据
1.首先我们拿到数据,数据必须按照一定的格式书写的.如用|区分字段,换行区分row 12107 | 心情1 | 今天的心情很不好啊. 12108 | 天气 | 今天天气还行. 12109 | 臭美 | ...
- 通过String获取字符数组
方法一: public void getChars(int start,int end,char c[],int offset) 作用是将当前字符串从start到end-1位置上的字符复制到字符数组c ...
- 【BZOJ2654】tree(生成树 二分)
题目链接 大意 给你一个无向带权连通图,每条边是黑色或白色,求一棵最小权的恰好有\(Need\)条白色边的生成树. 题目保证有解,输出最小权值. 其中每条边权在\([1,100]\)范围内. 思路 首 ...
- Note/Solution - 转置原理 & 多点求值
\[\newcommand{\vct}[1]{\boldsymbol{#1}} \newcommand{\mat}[1]{\begin{bmatrix}#1\end{bmatrix}} \newcom ...
- Java老码农心得:卷了这么多年,您真的卷会了吗?
前言 大家好,我是福隆苑居士,今天跟大家聊一下程序员在当下内卷成风的情况下,使用什么方法可以了解行业发展趋势,知道哪些该学,哪些可以略过,今年应该掌握什么,可以放弃什么,让自己时刻紧跟行业的步伐永不掉 ...
- MySQL数据库的导入方法
问题 如何导入MySQL数据库 解决方案 1. 概述MySQL数据库的导入,有两种方法:1) 先导出数据库SQL脚本,再导入:2) 直接拷贝数据库目录和文件. 在不同操作系统或MySQL版本情况下,直 ...
- jsp页面获取请求参数问题记录
同一个请求可以从请求路径中获取参数,使用param.参数名 window.location.href = "admin/page.html?pageNum="+pageNum+&q ...