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

时间:2014-05-29 16:48:05

标签: c++ memory-management vector stl containers

在德国编程书(约会到2012年)中称为“C ++fürC-Programmierer”(C ++ for C programmers,duh!),我作为参考购买了该文章,我在章节中找到了关于STL的一节(我'我会立即为你们翻译):

  

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

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

  

[...]

     

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

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

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

std::vector<int>* i = new std::vector<int>;
std::cout << malloc_size(i) << std::endl;

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

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

此致 卡森

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:11)

矢量对象本身只包含几个指针,因此您显示的32字节大小并不令人惊讶,并且它不会随着时间的推移而发生变化。

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

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

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

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

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

答案 2 :(得分:5)

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

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

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

您不需要malloc_size来了解预留了多少内存。只需使用v.capacity() * sizeof( elem_type )