繁体   English   中英

std::unordered_map::erase 实际上执行动态释放吗?

[英]Does std::unordered_map::erase actually perform dynamic deallocation?

不难找到有关 stl 容器操作的大 O 时间行为的信息。 但是,我们在硬实时环境中运行,我在查找有关其堆 memory 使用行为的信息时遇到了很多麻烦。

特别是有一位开发人员来找我询问 std::unordered_map。 我们允许在启动时是非实时的,所以他希望在启动时执行 a.reserve() 。 然而,他发现他在运行时会超限。 他使用的操作是用.erase() 进行查找、插入和删除。

我有点担心 that.reserve() 实际上阻止了以后的运行时 memory 分配(我真的不明白它对堆使用的作用的解释),但是 .erase() 特别是我没有看到任何保证它在调用时不会要求堆进行动态释放。

所以问题是 std::unordered_map::erase 的指定堆交互(如果有的话)是什么,如果它确实进行了释放,是否有某种技巧可以用来避免它们?

该标准本身并未指定容器分配模式。 这些实际上是从迭代器/引用失效规则派生的。 例如,如果插入的元素数量导致容器的大小超过其容量, vector::insert只会使所有引用无效。 这意味着重新分配发生了。

相比之下,唯一使引用无效的unordered_map操作是实际删除该特定元素的操作。 即使是重新散列(可能分配内存)也不会使引用无效(这就是为什么reserve什么都不改变的原因)。

这意味着每个元素必须与 hash 表本身分开存储。 它们是独立的节点(这就是为什么它有一个node_type提取接口),并且必须能够单独分配和释放。

因此,假设每次插入或删除代表至少一次分配/释放是合理的。

如果您对节点继续使用 memory 没问题,即使它们已从容器中删除,您也可以很容易地编写一个分配器 class,它基本上使释放成为 NOP。

相当多的实时系统基本上分配了他们将要使用的所有 memory,然后一旦他们完成初始化,他们既不分配也不释放 memory。这将允许您使用 unordered_map 做几乎相同的事情.

也就是说,我对这种情况下的好处有些怀疑。 unordered_map 的主要优势是支持通常很快的插入和删除。 如果您不打算在运行时进行插入,那么它很可能不是一个特别好的选择。

如果它是一个在初始化期间大部分被填充的集合,然后主要按原样使用,一些项目被“删除”,但在完成初始化后不再插入,那么使用简单的排序数组可能会更好,并且插值搜索(或者,如果数据的分布极其不可预测,则可能是二分搜索——但插值搜索通常更好)。 在这种情况下,我将通过简单地向每个项目添加一个 boolean 来说明该项目是否有效来处理删除。 通过将该值设置为 false 来擦除。 如果您在搜索过程中找到这样的值,您基本上会忽略它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM