【问题标题】:C++11: Is it safe to remove individual elements from std::unordered_map while iterating?C++11:迭代时从 std::unordered_map 中删除单个元素是否安全?
【发布时间】:2014-09-22 17:02:17
【问题描述】:

考虑在迭代时从关联容器中删除元素的规范算法:

for (auto iter = myMap.begin(); iter != myMap.end(); )
{
    if (/* removal condition */)
    {
        iter = myMap.erase(iter);
    }
    else
    {
        ++iter;
    }
}

在使用 C++11 std::unordered_map 容器时,我一直在不假思索地应用此算法。但是,在浏览了cppreference.com 上的std::unordered_map::erase 的文档后,我在阅读了以下注释后有点担心:

保留未擦除元素的顺序(这使得在遍历容器时可以擦除单个元素)(C++14 起)

基于此声明,我假设 C++14 标准中添加了语言,以确保库实现者在调用 std::unordered_map::erase 后保证排序。例如,也许这样的要求会限制实现在删除元素后不重新散列整个容器,而是只允许它从相应的桶中删除元素?

如果在 C++11 中没有这样的保证,并且如果我希望我的代码是可移植的,我是否必须担心如果我从 std::unordered_map 中删除一个元素,某些元素会被多次访问或根本不被访问在迭代期间?

【问题讨论】:

  • 参考引用 C++11 规则的this answer。对于从无序关联容器中擦除,只有被擦除元素的迭代器是无效的。所以你的代码是有效的。
  • @Praetorian:感谢您的澄清。我知道迭代器在擦除后仍然有效,但我担心的是,鉴于上面的 C++14 保证,将继续迭代直到最后产生相同的元素序列,就好像我没有删除元素一样?如果是这样,您知道为什么委员会认为有必要在 C++14 中添加上述说明吗?
  • 对不起,我误解了你的问题。 Here's 导致措辞变化的问题。我认为您的问题的答案是 - 标准 pre-C++14 不保证,在实践中保证。链接的报告也说明了这一点 - 无论如何,任何实际的实现都不会这样做。我会重新打开这个问题,也许有人会为你提供更好的答案。
  • @Praetorian:你对一个好问题有一个很好的答案。请把它放在我可以投票的地方。 :-)
  • @Howard 谢谢你,但我希望像你这样对至少一个标准库实现有深入了解的人会发布答案。无论如何,现在已经有一个答案说明了我在评论中所做的事情。

标签: c++ c++11 stl iterator unordered-map


【解决方案1】:

编辑:NoScript 的危险。 我运行了 noscript,它将 C11 和 C14 选项卡显示为一个框。 Praetorian 的回答是正确的,它在实践中得到保证,并在 c14 中正式化。

** 由于没有脚本,以下是错误的。

在 cplusplus 的底部它声明

只有被移除元素的迭代器和引用才会失效。

其余的不受影响。

未被操作删除的元素的相对迭代顺序被保留。

http://www.cplusplus.com/reference/unordered_map/unordered_map/erase/

在页面顶部,它声明它适用于 C++11...所以除非他们为 C++14 更新它,否则我认为它也适用于 C++11。 Praetorian 应该给出答案,你应该检查他的答案,因为即使 C++11 的标准不能保证(C++14 是这类事情的补丁),它在实践中也得到保证。

我找不到 STL 标准,我似乎放错了位置,或者我会去看看是否有保证我可以指出的文本。 :-/

【讨论】:

  • 感谢您提供附加链接,但是当我查看该页面时,声明 “保留了未被操作删除的元素的相对迭代顺序”, 是仅在 C++14 选项卡下列出。如果我读错了,请纠正我。否则,我会很感激编辑,因为我认为引用 cplusplus.com link 很有用。
  • 我没有打开脚本。它将两个选项卡显示为一个文本块。对不起:-(
  • 我接受了这个答案,因为它引用了 Praetorian 上面的评论,这正是我想要的。
猜你喜欢
  • 2011-02-21
  • 2015-04-03
  • 2019-01-15
  • 1970-01-01
  • 2014-01-04
  • 2011-07-13
  • 2013-09-01
  • 1970-01-01
相关资源
最近更新 更多