哪个向量和地图,使用更少的内存(大量数据和未知大小)
Posted
技术标签:
【中文标题】哪个向量和地图,使用更少的内存(大量数据和未知大小)【英文标题】:Which vector and map, uses less memory (large set of data and unknown size) 【发布时间】:2015-07-30 00:13:31 【问题描述】:我想知道在std::map
和std::vector
之间哪个容器使用的内存更少,并且有大量数据。
很多帖子都在讲效率,我的重点不是效率而是内存消耗。那么,如果我们不知道我们的数据数量(在我的例子中可能超过 12,000,000 个条目,每个条目都是一个 20 个字符的字符串),那么 map 真的比 vector 更好吗?
【问题讨论】:
map
和 vector
做不同的事情:map
存储键值对,而不是单个值。通常,关联容器具有更多开销,因为它们将指针存储在数据旁边并单独分配每个节点;但是vector
需要连续的内存,如果你让它重新分配太频繁可能会导致碎片。唯一真正的答案是衡量。
Vector 包含一个连续的数组,因此它恰好占用size() * sizeof(value_type)
字节的动态存储空间。 Map 每个条目有一个动态节点,这会增加相当多的开销。
我会考虑在这里滚动我自己的 - 有 1200 万个条目,你可以证明它是合理的 - 你想节省多少内存?一个包含 1200 万个 20 个字符的容器可能比一个包含 1200 万个 20 个字符(又名字符串)的容器更好。就此而言,[a-z] 的 20 个字符串具有 10^28 个可能值的顺序,在这种情况下,可以将每个字符串表示为 96 位整数吗?你准备好到什么程度了?
你可以看看info.prelert.com/blog/stl-container-memory-usage和***.com/questions/11841357/…
@AndyNewman,我知道,但对于每个字符串,我都有一个包含其他数据的容器。每个字符串都不一样。
【参考方案1】:
std::vector
必须在连续的内存中组织字符串。 (标准坚持这一点)。因此,对于std::vector
,示例中的连续内存量至少为sizeof(string) * 12,000,000
。幸运的是,每个字符串可能在堆中都有自己的缓冲区:对于使用固定缓冲区来存储短字符串的 std::string
实现来说,20 个字符是分界线。
std::map
不会出现这种连续性问题,因此在这种情况下可能是一个更好的容器。但是,总的来说,它可能会消耗更多的内存。但该内存将更容易被程序获取。
【讨论】:
【参考方案2】:取决于您要解决的问题。基本上,std::vector 使用一个行内存(因为你的数据很大,确保你有一个),但是 std::map 可以从内存的不同部分获取每个节点。相反,由于节点之间的指针操作,std::map 对相同数据使用更多内存。
【讨论】:
但是在调整大小时,向量是否会将他的所有数据复制到另一个连续的内存行中?还是保留两行? 如果你的向量大小是 n,并且你调用 resize(m) 那里 m > n ,它只是将必要的 mn 部分添加到你的向量中,如果 m 不正确,如果m对于您记下的特定大小,您可能需要考虑一些不会走极端的东西:不是连续的内存数组,也不是基于单节点的树。
有些选项是
a(内存驻留)B tree
一棵数字树
【讨论】:
【参考方案4】:如果您想将数据保存在连续内存中,您应该选择std::vector
,否则如果您更喜欢基于节点的数据结构并且需要大量插入和删除操作,我建议您使用std::list
而不是std::map
。
如果您更喜欢基于节点的数据结构并在数据结构的元素之间保持顺序并且没有键值对,我更喜欢std::set
而不是std::map
。
如果您更喜欢基于节点的数据结构,其中数据作为键值对并保持元素之间的顺序取决于数据的键值,我更喜欢std::map
【讨论】:
以上是关于哪个向量和地图,使用更少的内存(大量数据和未知大小)的主要内容,如果未能解决你的问题,请参考以下文章