C++ 调用reserve()后std::vector的空间复杂度

C++ 调用reserve()后std::vector的空间复杂度,c++,visual-c++,vector,std,C++,Visual C++,Vector,Std,我试图理解调用reserve()后std::vector空间复杂性的演变方式 代码如下: vector<SparseData<T_Indices, T_Values>> v1 = vector<SparseData<T_Indices, T_Values>>(); v1.reserve(341); vector<SparseData<T_Indices, T_Values>> v2 = vector<SparseDat

我试图理解调用reserve()后std::vector空间复杂性的演变方式

代码如下:

vector<SparseData<T_Indices, T_Values>> v1 = vector<SparseData<T_Indices, T_Values>>();
v1.reserve(341);
vector<SparseData<T_Indices, T_Values>> v2 = vector<SparseData<T_Indices, T_Values>>();
v2.reserve(342);
vector v1=vector();
v1.储备(341);
向量v2=向量();
v2.储备(342);
使用包含3个整数(每个4字节)的
SPARA

v1成本是理论成本
O(v1)=341*3*4=4092字节
。好的

我的问题是成本。我期望
O(v2)=342*3*4=4104字节
,但实际成本是
4151字节
。有一个
47字节的
delta我无法理解

我正在使用Visual Studio 2017社区诊断工具(快照堆)测量空间,我相信这是值得信任的

这些
47字节的含义是什么?它们可能代表什么

提前谢谢

编辑:我编辑了最初的帖子,以便类名与截图匹配。下面是调用reserve(341)(resp.reserve(342))后v1(resp.v2)的测量值。请注意,两个元素的“值”与其他元素不同。此外,v2包含345个
spara
元素,对第一个
4140字节
进行了解释:好的,这是或更大的部分:

如果n大于当前向量容量,该函数将使容器重新分配其存储,并将其容量增加到n(或更大)

仍在查找
11字节
delta-tho


可能会发生一些事情

  • std::vector::reserve
    允许过度分配空间。这是因为允许分配器过度分配空间。因此,当您请求4014字节时,您可能看到的正是MSVC的分配器分配的内容

  • Visual Studio 2017社区诊断工具的粒度可能不够精细,它不仅可以查看向量的分配,还可以捕获从其他地方分配的内存

  • 1和2的组合


  • 基于你随后的实验

    v2.reserve(342) = 4151 
    v2.reserve(343) = 4163
    
    4163-4151=12,其中=4*3,这是无开销的预期增长

    两个内存使用级别之间的差异为12字节。因此,47字节可能只是编译器用于跟踪与向量相关的其他细节的开销

    可能是reserve()分配了特定的内存量,而实际上添加元素会增加内存使用量

    在任何情况下,reserve()都应设置为您希望不超过的级别。随着向量大小的增加,运行时必须重新分配内存,并将旧向量复制到新的内存空间。因此,我相信您已经知道,reserve()不应该以增量方式调用


    与每次添加1000个元素后添加1000个元素的内存使用量相比,从1到1000的reserve(n)调用图会很有趣。

    再次运行v3.reserve(343)的代码。通常情况下,向量算法会添加内存块进行存储。它被实现为一个数组,在块中动态增长。您应该看到下一步的增量将为零或更小的值,因此您将看到一个用于增加大小的步长函数。
    reserve
    将容量增加到大于或等于请求的值。您不能保证它会准确地分配
    N
    字节。刚刚
    =N
    。完成后,v3的测量成本为4163字节。理论成本是4116(343*4*3),所以我们仍然有47字节的增量。我用reserve(3000)试过了,但仍然测量了47字节的差异。@Spazz你有没有打开或关闭优化?这会产生很大的差异。您会注意到,您正在查看的值对应于
    0xCDCDCDCD
    或刚刚分配但未初始化的干净内存。也可能是调试分配器。。。这是一个保护页