我怎么知道“ rehash”是否在插入unordered_map之后发生

How do i know whether `rehash` happened after i insert into an unordered_map?

本文关键字:map 之后 unordered 插入 rehash 是否 我怎么知道      更新时间:2023-10-16

我了解unordered_ STL容器保留许多桶,这些存储桶在数字上取决于容器中的元素数量。插入时,如果打破一定的限制,容器将重新使用更多的存储桶,因此每个存储桶的搜索速度较小,更快。这使迭代器无效。

这意味着我不应该将迭代器保留到unordered容器中。除了可以,如果我在重新进行后更新它们。但是我找不到一种可靠的方法来检查insert(无论是emplace还是其他(是否引起了重新启示。

我应该监视bucket_count()

cppreference说Rehashing occurs only if the new number of elements is greater than max_load_factor()*bucket_count()。那是garanteed吗?执行以下操作会可靠吗?

bool will_rehash = (max_load_factor()*bucket_count()) > size()+1;

我不认为一旦哈希映射增长,就不会进行重新限制(作为实际参与的过程(发生:

  1. 计算哈希是(相对(的计算
  2. 请参阅下面的示例,我迅速编译,在那里我制作了一个自定义哈希函子,该函数跟踪了它的时间:
    • 每当桶数增加时,就没有迹象表明哈希函数被称为=>我们可以推断出重新扣动会发生,而不是重新敲打

这意味着,可以观看桶数以推断是否应无效迭代器(预定在重新敲击时发生(

(
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
typedef unordered_map<string, string> str_map;
struct my_hash {
    void        reset(void) { calls_ = 0; }
    size_t      calls(void) { return calls_; }
    size_t      operator()(const string& key) const {
                 ++my_hash::calls_;
                 return hash_fn_(key);
                }
 private:
        str_map native_hash_fn_;
str_map::hasher hash_fn_{native_hash_fn_.hash_function()};
  static size_t calls_;
};
size_t my_hash::calls_ = 0;

int main ()
{
 typedef unordered_map<string, string, my_hash> myMapType;
 myMapType mymap(1, my_hash());
 myMapType::hasher hash = mymap.hash_function();
 cout << "mymap has " << mymap.bucket_count() << " buckets" << endl;
 mymap["abc1"] = "blah"; // add 3 values
 mymap["abc2"] = "blah"; // just to see the hash calls tracking
 mymap["abc3"] = "blah"; // is working
 cout << "hash calls: " << hash.calls() << endl;
 hash.reset();
 for(size_t i=0; i < 10; ++i) {
  mymap[to_string(i)] = "blah";
  cout << "buckets: " << mymap.bucket_count() << endl;
  cout << "hash calls: " << hash.calls() << endl;
  hash.reset();
 }
 cout << "mymap has " << mymap.bucket_count() << " buckets" << endl;
}

输出:

mymap has 2 buckets
hash calls: 3
buckets: 5
hash calls: 1
buckets: 11
hash calls: 1
buckets: 11
hash calls: 1
buckets: 11
hash calls: 1
buckets: 11
hash calls: 1
buckets: 11
hash calls: 1
buckets: 11
hash calls: 1
buckets: 23
hash calls: 1
buckets: 23
hash calls: 1
buckets: 23
hash calls: 1
mymap has 23 buckets

免责声明:不过,我坚信在容器尺寸变化后引用迭代器并不是一个好的编程实践。即使它可能不会引起某些致命/未定义的行为,也可能(很可能(会导致一些某些副作用对编程逻辑。如果使用Hash-Map,请考虑使用begin()迭代器的情况:插入几个插入/Emplacements之后,它将不再是真正的begin。即使没有重新捕捉,也可能会安装一些新条目(这可能会影响编程逻辑(。