Я не думаю, что повторное хеширование (как процесс, в котором фактически задействована хеш-функция) происходит после того, как растет хеш-карта:
- вычисление хеша (относительно) вычислительнодорогой
- см. ниже мой пример, который я быстро скомпилировал, где я создал специальный хеш-функтор, который отслеживает время его вызова:
- всякий раз, когда увеличивается количество сегментов, нет никаких признаков того, что хеш-функция былаПри вызове => мы можем сделать вывод, что повторное ведение происходит вместо повторного хеширования
Это означает, что можно отслеживать количество сегментов, чтобы определить, следует ли считать итератор недействительным (предсказал, что аннулирование произойдет в момент повторного размещения)
#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
Отказ от ответственности: хотя я твердо верю, что не рекомендуется программировать ссылки на итераторы послеКонтейнер изменился в размере.Даже если это может не привести к фатальному / неопределенному поведению, оно может (и, скорее всего, вызовет) некоторые побочные эффекты на логику программирования.В случае с хэш-картой рассмотрим ситуацию с итератором begin()
: после нескольких вставок / вставок он больше не будет истинным begin
.Даже если перебазирование не произошло, некоторые новые записи могут быть установлены перед ним (что может повлиять на логику программирования).