std :: vector/Programming book神话的默认大小?

hel*_*rve 10 c++ containers memory-management stl vector

在我购买的德语编程书(约会到2012年)中称为"C++fürC-Programmierer"(C++ for C programmers,duh!)作为参考我在关于STL的章节中找到了以下部分(我将正确翻译)离开你们):

大多数STL实现在内存管理方面都很慷慨.矢量的分配主要以1kb块为例进行.如果分配一些向量,那么剪辑并不重要,但是如果你创建十到几十个向量,它就会发生.

我找不到任何证实这一点的消息来源.我知道这取决于实现,但我找不到任何确认即使是一个平台的东西.Cplusplus.com 仅表明:

[...]

因此,与数组相比,向量消耗更多内存以换取管理存储和以有效方式动态增长的能力.

到目前为止我尝试了什么?

我写了一个小的C++程序,利用OS X特定的malloc_size()函数,但我从来没有使用它,我很确定我做错了.如果我按照以下方式做某事:

std::vector<int>* i = new std::vector<int>;
std::cout << malloc_size(i) << std::endl;
Run Code Online (Sandbox Code Playgroud)

Cout只是告诉我32,这可能是一个int的大小,因此证明了作者部分错误,但我并不是真的相信自己的努力.

有谁知道更好或知道资源?提前致谢.

此致,卡森

T.C*_*.C. 17

您的代码不会衡量您希望它衡量的内容.该vector结构本身通常是相当小的.它基本上包含跟踪分配的内存和指向该内存的指针所需的一些字段.你想要衡量的是不同的.

------        -------------------
| i  |------> | A few fields    |
------        | (e.g., size and |
              |  capacity)      |         -------------------
              |-----------------|         | Space allocated |
              |   pointer       |-------> | for elements    |
              -------------------         -------------------
                 ^                            ^
               What your code               What you want to
               measures                     measure
Run Code Online (Sandbox Code Playgroud)

您可以vector为该轨道提供自定义分配器,并报告所请求分配的大小.我的计算机上的GCC 4.8.1实现没有为默认构造的向量分配内存(因为它没有元素),并使用注释中提到的双倍大小的每个增长实现.

  • @Carson:我知道没有stdlib作者是对的,但这并不意味着它从未发生过.我所知道的可能在德国很常见. (2认同)

Adr*_*thy 11

向量对象本身只包含几个指针,因此您显示的32字节大小并不令人惊讶,并且它不会随着时间而改变.

我相信本书的内容是指为矢量内容分配的存储空间.当您向向量添加项目时,它将分配空间来存储它们,但该空间不会反映在malloc_size中.

您可以通过调用向量的capacity()方法来计算向量分配了多少空间.这将告诉您它可以容纳多少项目.如果您想要以字节为单位的大小,您可以通过元素类型的大小来倍增容量.

引用的文字谈论了1 KB块.较旧的动态容器在需要生长时使用线性方案.但是标准放在std :: vector上的运行时复杂性要求不允许这种方法.相反,矢量必须增长其当前大小的某个百分比.

许多实现使用100%.因此,如果一个向量当前有10个项目的空间,并且它需要增长,它将调整最多20个项目.如果它需要进一步增长,它将调整最多40个项目,依此类推.因此,在最坏的情况下,您最终可以得到一个分配了几乎两倍于实际所需空间的向量.一些实现使用50%,这仍然满足运行时复杂性要求,而不会增长太快或"浪费"尽可能多的空间.(使用小于100%的因子至少还有一个优点,但它与此讨论无关.)

在具有虚拟内存的现代计算机上,任何一种方法通常都很好 - 性能将比未使用的内存更重要.如果您使用的是资源有限的嵌入式系统,则可能需要更直接的控制.像复制和交换这样的技巧可以将具有过剩容量的向量修剪到接近实际需要的大小.

  • 没有足够的上下文(或翻译中丢失的东西)来确定作者是对还是错.从某种意义上说,即使几何增长,实现仍然可能选择块大小的倍数,如1 KB.没有符合标准的std :: vector版本使用线性增长,但是当人们实现自己的动态数组时,线性增长很常见. (2认同)

Pot*_*ter 5

这本书在几个方面是不正确的.std::vector根据几何系列增长,因此将始终填充一定百分比(除非您的erase元素).剪辑可能会相加,但一般情况下它会与实际使用的内存成比例.对于实际使用的馏分,50-65%是典型的最坏情况下限.

这不依赖于实现.需要几何系列以确保push_back花费O(1)摊销时间.线性增长将导致O(N)摊销时间(或O(N ^ 2)到push_backN个值的序列).

实现可以决定非空的不可忽略的最小大小vector,但没有充分的理由这样做,因为小的很常见.同样,默认初始化的向量总是被实现为根本不保留动态存储器.

您不需要malloc_size了解保留多少内存.只是用.v.capacity() * sizeof( elem_type )