【问题标题】:Are STL associative containers containing containers a performance issue?包含容器的 STL 关联容器是性能问题吗?
【发布时间】:2017-03-01 10:54:43
【问题描述】:

在我的场景中,我有一个std::map<std::string, std::vector<cCustomClass> >,但同样的问题也适用于std::set。这些向量可能会变得非常大(超过 100000 个元素),因此我担心如果向地图添加更多元素,是否会重新分配或复制向量。

核心问题是:地图会在某个时候复制大向量吗?如果是,它的成本是否与std::vector::capacity() 成正比?

如果两者的答案都是肯定的,我有什么选择?我的第一个解决方案是使用std::map<std::string, std::vector<cCustomClass> * > 和(或智能指针),但我想知道这是否有必要。

我使用 C++03。如果答案取决于标准,我很感激任何关于它的评论。

【问题讨论】:

  • 将新元素插入地图(或集合)或删除元素不会使迭代器无效,表明内容不会被移动或复制。但没有绝对的保证。
  • 不,map 不会随机复制元素。你能展示一些执行不必要复制的代码吗?
  • 你能说得更具体些吗? “相当大”有多大?你想用地图做什么?
  • 我认为只有当你 insert() 一个已经填充到地图中的大向量时,才会出现性能问题,因为 move-insert 仅在 C++11 之后可用。所以当插入这么大的向量时,整个东西都会被复制到地图中。但这只会影响您插入的一个地图项,不会复制现有的地图项。

标签: c++ performance stl containers c++03


【解决方案1】:

地图会在某个时间点复制大矢量

没有。 mapset 和其他关联容器是基于节点的。节点为每个条目独立分配,通过指针连接,在容器增长、收缩、重新平衡自身等时不需要复制或重新分配。

您对此的保证是对各种容器的迭代器失效要求。比较

  • std::map::insert

    没有迭代器或引用无效

    如果迭代器没有失效,则它们指向的元素必须将其位置保留在内存中,因此插入地图不需要复制或移动任何现有元素。

  • std::vector::insert

    如果新的size() 大于capacity(),则所有迭代器和引用都将失效。否则,只有插入点之前的迭代器和引用保持有效。过去的迭代器也失效了。

    如果迭代器无效,则元素可能被移动、复制或移动了值。特别是对于向量,元素插入后必须被移动/复制,以便为新元素腾出空间。

    如果向量需要重新分配才能增长,则必须将所有元素移动/复制到新分配的区域。

值得注意的是,尽管map 并不会真正影响您,但现代编译器会在可能的情况下移动 元素。例如,您的大向量将被移动,这比复制它便宜得多 - 如果您可以更新到 C++11 或更高版本,那就是。

【讨论】:

    猜你喜欢
    • 2022-11-13
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2019-05-29
    相关资源
    最近更新 更多