【问题标题】:Can we store unordered_map<T>::iterator?我们可以存储 unordered_map<T>::iterator 吗?
【发布时间】:2013-05-27 23:41:19
【问题描述】:

参考 http://www.careercup.com/question?id=17188673 by chetan.j9

void Insert( string s ) {
    if( IsElementPresent(s) )
        return;

    myMap[s] = myMapVector.size();
    unordered_map<string,int>::iterator it = myMap.find(s);
    myMapVector.push_back(it);      
}

问题> 我们可以存储 unordered_map 的迭代器以供以后检索吗?根据我的理解,插入或删除元素后,迭代器会失效。

谢谢

【问题讨论】:

标签: c++


【解决方案1】:

@syam 的回答是正确的 (+1),但我认为引用唯一的权威来源 C++11 标准很有用:

(§23.2.5/13) insertemplace 成员不应影响对容器元素的引用的有效性,但可能会使容器的所有迭代器无效。擦除成员只能使迭代器和对被擦除元素的引用无效。

(§23.2.5/14) insertemplace 成员不应影响迭代器的有效性,如果 (N+n)

(将其放在上下文中:§23.2.5 是关于无序关联容器的部分,因此它适用于 std::unordered_setstd::unordered_mapstd::unordered_multisetstd::unordered_multimap。) 这意味着:

  1. 如果你想将n元素插入到名为hashunordered_map中,可以检查是否

     hash.size() + n < hash.max_load_factor() * hash.bucket_count()
    

    是真的。如果为 false,则在插入期间所有迭代器都将失效。如果为 true,迭代器将保持有效。

  2. 即使迭代器在此操作中失效,对元素本身的引用仍然有效。

  3. 如果你erase 元素,只有指向这些元素的迭代器才会失效;其他迭代器将保持有效。

【讨论】:

  • 我在理解第2点时有问题。你能给我举个例子吗?谢谢
  • @q0987 例如,如果您获得了对存储在哈希中的值的引用,例如int &amp;val = myMap["hello"];,那么即使您插入尽可能多的元素来触发重新分配,val 仍然是对为字符串 "hello" 存储的整数的有效引用。如果您从迭代器中获取引用,情况也是如此。迭代器稍后可能会失效,但对值的引用将保持有效。
  • 检查stackoverflow.com/questions/6438086/iterator-invalidation-rules 插入向量。 vector:插入点之前的所有迭代器和引用不受影响,除非新容器大小大于之前的容量(在这种情况下,所有迭代器和引用都无效)[23.2.4.3/1]
  • @q0987 我不知道你想告诉我什么。但我的回答提到了std::unordered_map,而不是std::vector,因为这就是你的问题所在。
  • 很好的答案。我想了解如何在重新散列后保持引用的有效性。我在哪里可以读到这方面的信息?
【解决方案2】:

只有在发生重新散列时(即,如果新元素的数量大于或等于max_load_factor()*bucket_count()),插入项才会使所有迭代器无效。否则没有迭代器无效。

删除一个项目只会使被删除元素的迭代器无效,而不是其他不相关的元素。

来源:std::unordered_map::insertstd::unordered_map::erase

当然,这些规则仅适用于std::unordered_map。其他容器可能有不同的失效规则,请自行查阅文档。

【讨论】:

  • 由于不知道什么时候失效,insert的实现是不正确的。对吗?
  • @q0987 我们实际上知道失效发生的时间(规则很清楚)。如果您事先知道最大项目数,那么您可以事先reserve,然后即使您插入,也可以安全地存储迭代器,只要您不超过保留的最大值。但是,当然,如果您想插入未知数量的项目,那就是另一回事了,并且在您仍在插入项目时存储迭代器确实不是一个好主意。
  • 严格来说,重新散列的条件是新元素的数量大于或等于您给出的公式(或者,因为我们在谈论浮点数,最好使用小于和否定语句)。
  • @jogojapan:感谢您的精确,我已经在我的回答中更正了它。看起来 cppreference.com 有一个小错误,我会编辑它,但他们使用的那些模板一团糟,我不想破坏任何东西。 +1 为您引用标准。
  • @jogojapan 和 syam:感谢您注意到文档错误 -- 我已更新 en.cppreference.com/w/cpp/container/unordered_map/insert
猜你喜欢
  • 2016-11-26
  • 2011-02-26
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 2018-08-23
相关资源
最近更新 更多