gpt4 book ai didi

c++ - std::vector 的容量如何自动增长?费率是多少?

转载 作者:IT老高 更新时间:2023-10-28 21:43:41 33 4
gpt4 key购买 nike

我一直在阅读这本书:C++ Primer, Third Edition By Stanley B. Lippman, Josée Lajoie,在 Article 6.3 How a vector Grows Itself 下给出的程序中发现了 1 个错误,该程序遗漏了一个“<"在 couts:

#include <vector>
#include <iostream>

using namespace std;

int main() {
vector<int> ivec;
cout < "ivec: size: " < ivec.size() < " capacity: " < ivec.capacity() < endl;

for (int ix = 0; ix < 24; ++ix) {
ivec.push_back(ix);
cout < "ivec: size: " < ivec.size()
< " capacity: " < ivec.capacity() < endl;
}
}

在那篇文章的后面:

"Under the Rogue Wave implementation, both the size and the capacityof ivec after its definition are 0. On inserting the first element,however, ivec's capacity is 256 and its size is 1."

但是,在更正和运行代码时,我得到以下输出:


ivec: size: 0 capacity: 0
ivec[0]=0 ivec: size: 1 capacity: 1
ivec[1]=1 ivec: size: 2 capacity: 2
ivec[2]=2 ivec: size: 3 capacity: 4
ivec[3]=3 ivec: size: 4 capacity: 4
ivec[4]=4 ivec: size: 5 capacity: 8
ivec[5]=5 ivec: size: 6 capacity: 8
ivec[6]=6 ivec: size: 7 capacity: 8
ivec[7]=7 ivec: size: 8 capacity: 8
ivec[8]=8 ivec: size: 9 capacity: 16
ivec[9]=9 ivec: size: 10 capacity: 16
ivec[10]=10 ivec: size: 11 capacity: 16
ivec[11]=11 ivec: size: 12 capacity: 16
ivec[12]=12 ivec: size: 13 capacity: 16
ivec[13]=13 ivec: size: 14 capacity: 16
ivec[14]=14 ivec: size: 15 capacity: 16
ivec[15]=15 ivec: size: 16 capacity: 16
ivec[16]=16 ivec: size: 17 capacity: 32
ivec[17]=17 ivec: size: 18 capacity: 32
ivec[18]=18 ivec: size: 19 capacity: 32
ivec[19]=19 ivec: size: 20 capacity: 32
ivec[20]=20 ivec: size: 21 capacity: 32
ivec[21]=21 ivec: size: 22 capacity: 32
ivec[22]=22 ivec: size: 23 capacity: 32
ivec[23]=23 ivec: size: 24 capacity: 32

容量是否随着公式2^N增加,其中N是初始容量?请解释一下。

最佳答案

标准要求 vector 容量增长的速率是指数的(恕我直言,这超出了规范)。标准对此进行了规定,以满足 push_back 操作的 摊销常数时间 要求。 摊销常数时间意味着什么以及指数增长如何实现这一点很有趣。

每次 vector 的容量增加时,都需要复制元素。如果您在 vector 的整个生命周期内“摊销”此成本,结果表明,如果您以指数因子增加容量,您最终会得到摊销的恒定成本。

这可能看起来有点奇怪,所以让我向你解释一下它是如何工作的......

  • size: 1 capacity 1 - 未复制任何元素,复制的每个元素的成本为 0。
  • size: 2 capacity 2 - 当 vector 的容量增加到 2 时,必须复制第一个元素。每个元素的平均拷贝数为 0.5
  • size: 3 capacity 4 - 当 vector 的容量增加到 4 时,必须复制前两个元素。每个元素的平均拷贝数为 (2 + 1 + 0)/3 = 1。
  • 大小:4 容量 4 - 每个元素的平均拷贝数为 (2 + 1 + 0 + 0)/4 = 3/4 = 0.75。
  • 大小:5 容量 8 - 每个元素的平均拷贝数为 (3 + 2 + 1 + 1 + 0)/5 = 7/5 = 1.4
  • ...
  • 大小:8 容量 8 - 每个元素的平均拷贝数为 (3 + 2 + 1 + 1 + 0 + 0 + 0 + 0)/8 = 7/8 = 0.875
  • 大小:9 容量 16 - 每个元素的平均拷贝数为 (4 + 3 + 2 + 2 + 1 + 1 + 1 + 1 + 0)/9 = 15/9 = 1.67
  • ...
  • 大小 16 容量 16 - 每个元素的平均拷贝数为 15/16 = 0.938
  • 大小 17 容量 32 - 每个元素的平均拷贝数为 31/17 = 1.82

如您所见,每次容量跳跃时,拷贝数都会增加数组之前的大小。但是由于数组在容量再次跳跃之前必须翻倍,所以每个元素的拷贝数始终保持小于 2。

如果你将容量增加 1.5 * N 而不是 2 * N,你最终会得到非常相似的效果,除了每个元素的拷贝上限会更高(我认为它会是 3)。

我怀疑一个实现会选择 1.5 而不是 2 既可以节省一点空间,也因为 1.5 更接近 golden ratio .我有一种直觉(目前没有任何硬数据支持),符合黄金比例的增长率(因为它与斐波那契数列的关系)将被证明是现实世界负载的最有效增长率在最大限度地减少使用的额外空间和时间方面。

关于c++ - std::vector 的容量如何自动增长?费率是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5232198/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com