unordered_map中的存储区计数

时间:2017-03-01 05:07:52

标签: c++ heap-memory unordered-map dynamic-allocation g++4.9

在下面给出的示例程序中(来源:http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/

// unordered_map::rehash
#include <iostream>
#include <string>
#include <unordered_map>

int main ()
{
  std::unordered_map<std::string,std::string> mymap;

  mymap.rehash(20);

  mymap["house"] = "maison";
  mymap["apple"] = "pomme";
  mymap["tree"] = "arbre";
  mymap["book"] = "livre";
  mymap["door"] = "porte";
  mymap["grapefruit"] = "pamplemousse";

  std::cout << "current bucket_count: " << mymap.bucket_count() << std::endl;

  return 0;
}

输出变为:

current bucket_count: 23

为什么铲斗数量变为23? 什么是对堆积的影响?堆分配什么时候完成?在桶重新插入或实际插入?动态释放完成后?何时使用clear()erase()或两者兼而有之?

2 个答案:

答案 0 :(得分:2)

libstdc ++使用的默认重新策略策略是上升到大于或等于请求数量的最小素数桶数。 23是20以上的最小素数。

答案 1 :(得分:2)

哈希表的大小通常大于“舒适地”大于表中存储的项目数。这是因为映射到同一桶的两个不同项的概率随着哈希表填充而增加。

正如维基百科(image source)中的下图所示,对于某些冲突解决方法,如果哈希表的“加载因子” - 使用的桶的百分比,则哈希表的行为会受到严重影响 - - 超过一定比例。

Cache misses per look-up in a hash table

因此,存储区的数量应始终大于哈希表中的元素数。

将桶数作为素数有助于确保哈希表中的条目均匀分布在其中。通常,任何与桶数共享一个共同因子的密钥都将被散列到一个桶,该桶是该因子的倍数。因此,如果将桶数设置为20并且哈希值恰好是偶数,则会浪费表空间的大约50%。如果您的密钥具有4,5或10等因素,则情况会更糟。

了解上述内容后,您可以看到为什么哈希表可能比您指定的更大:额外空间(通常)有助于提高性能。您还可以看到为什么垃圾箱的数量将成为主要因素:因为这样可以更好地利用您拥有的空间。结合这些使得23看起来像是一个合理的选择。