vector扩容机制

在学习了vector的时候,总说linux下是以二倍扩容的,VS是以1.5倍扩容的。

但是想一想为什么扩容是这样的呢,为什么不能是3倍或者其他倍数呢? 所以带着这些疑问,接着往下看。

首先,我们要知道vector的扩容机制:当向vector插入元素的时候,即当_finish == _end_of_storage,可能就会触发扩容机制。

扩容有二种方式:

  • 等长个数扩容
  • 倍数扩容

等长个数扩容

等长个数扩容,新空间都是在原来的空间基础上增加K个空间。每当触发扩容的时候,就会将旧空间的数据移动到新空间去,同时将旧空间释放掉。

倍数扩容

假设向vector中插入n个元素,每当_finish== 2 ^k(0,1,2,3....)时,就会出现扩容。下面以VS和linux来观察看。

复制代码
void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

VS下的测试结果:

linux下的测试结果:

可以看出,VS下的扩容差不多是以1.5倍来扩容的,而linux下的扩容是以2倍来扩容的。那么问题来了,为什么这样???

为什么都会选择倍数扩容

这是因为以等长个数来扩容的话,需要插入元素和移动元素操作总和是O(N),而以倍数扩容是O(1)。

而且VS和linux下都是以倍数扩容,还有一些原因是如果以等长个数扩容,那么个数应该是多少呢?如果太小的话,就可能导致频繁的扩容;如果太大的话,就可能出现一种情况,如果有100个元素,这是只需要再插入一个元素,但是需要扩容100个,这就导致了浪费了99个的空间。

为什么选择1.5倍或者2倍来扩容,而不是3倍或者其他倍数

最佳的扩容倍数

要想对空间的利用率最高,就是F(N-1) + F(N-2) >= F(N) ,时间上是F(N-1) + F(N-2) = F(N),这不就是1, 2 3 5 8....,所以最佳的扩容机制就是1.618

linux下为什么选择二倍扩容

我们都知道linux下都是通过页来管理内存的,通常是4KB,都是2的倍数。

这样做有三个好处:

  • 减少内存分配次数:以二倍的方式扩容可以减少内存分配的次数,每次扩容后,可以容纳更多的容量。
  • 提高性能:二倍的扩容机制可以更好的利用linux系统分配的机制,减少内存分配和释放的频率,提高性能。
  • 减少内存碎片:以二倍的方式扩容可以减少内存碎片,因为如果每次扩容都是增加一些小的容量,就有可能导致小的内存散布在堆上,增加了内存碎片的风险。

像linux下的伙伴系统就是以2的幂次方来分配内存和管理的一种算法,综合考虑,就理解了为什么linux下为什么要选择以二倍的扩容机制。

相关推荐
Dream it possible!43 分钟前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
翔云1234561 小时前
RocksDB中,客户端每写入一次数据,需要访问几次磁盘
运维·数据库·mysql
心抵鹊1 小时前
算法之双指针系列(一)
算法·leetcode
十二1 小时前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯
爱莉希雅&&&2 小时前
GitLab 完整学习笔记
linux·运维·服务器
小此方2 小时前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
Pniubi3 小时前
力扣560.和为k的子数组
算法·leetcode·职场和发展
小杨爱科普3 小时前
制造业上自动化改造,改造部分的专利到底归谁
运维·经验分享·自动化
D e re k ZH3 小时前
C++ 从零入门(一):基础语法与程序结构
数据结构·c++·算法
Pniubi4 小时前
力扣438.找到字符串中所有字母异位词
算法·leetcode·职场和发展