我是C ++的新手,并且在unordered_map(或hash_map)方面存在以下问题:
#include <unordered_map>
#include <iostream>
using namespace std;
int main()
{
unordered_map<int,int> h1;
int temp1=0;
h1.insert(pair<int,int>(0,temp1));
unordered_map<int, unordered_map<int,int>> h2;
h2.insert(pair<int, unordered_map<int,int>>(1,h1));
unordered_map<int, unordered_map<int,int>>::iterator h2_itor=h2.find(1);
h2_itor->second.find(0)->second++;
unordered_map<int, unordered_map<int,int>> h3;
for(int i=0;i<100;i++)
{
int first=rand()%10;
int second=rand()%10;
unordered_map<int, unordered_map<int,int>>::iterator h3_itor=h3.find(first);
if(h3_itor!=h3.end())
{
unordered_map<int,int> submap=h3_itor->second;
unordered_map<int,int>::iterator submap_itor=submap.find(second);
if(submap_itor!=submap.end())
submap_itor->second++;
else
submap.insert(pair<int,int>(second, 1));
}
else
{
unordered_map<int,int> submap;
submap.insert(pair<int,int>(second,1));
h3.insert(pair<int, unordered_map<int,int>>(first,submap));
}
}
return 0;
}
输出很奇怪。对于h1和h2,似乎有效,这意味着更新了h1中带有键0的值(递增1)。虽然这看起来微不足道,但对于h3,我随机插入一些&#34;对&#34; (第一个,第二个)并使用哈希映射计数,计数似乎无法更新。例如,它可能是这样的:
insert 1 -> 7 -> 1
...
now update 1 -> 7 -> 1 to 1 -> 7 -> 2 using my code
fetch: h3.find(1)->second.find(7)->second : it's still 1 but not 2!
表示更新值不成功。我知道在Java中这种情况从未发生过。那么这个问题在哪里呢?
答案 0 :(得分:1)
问题在于:
unordered_map<int,int> submap = h3_itor->second;
这会导致整个子图复制到您的新本地submap
对象中。当你离开范围时,你所做的所有修改都会丢失。
相反,您可以使用对要修改的实际hashmap元素的引用:
unordered_map<int,int> &submap = h3_itor->second;
这一个&
应该解决所有问题。
答案 1 :(得分:0)
这是代码第二部分的重构版本(我认为)。我也在生成一致的测试数据集,因此我们可以在每次运行时重现行为(随机性是测试的一种诅咒)。
这是代码。问题是什么?
set
答案 2 :(得分:0)
不是一个真正的答案,只是一个FYI:如果这不仅仅是使用迭代器的练习,那么有一个更简单的方法:
unordered_map<int, unordered_map<int,int>> h3
h3[0][0] = 1;
for (int i=0; i<100; i++ ) {
int first=rand()%10;
int second=rand()%10;
h3[first][second]++;
}
这是有效的,因为如果缺少值,unordered_map::operator[]
将默认构造并插入它。对于地图,这是一个空地图,对于一个int,它是零。
如果您想要其他默认设置,可以使用unordered_map::emplace
,例如:
unordered_map<int, unordered_map<int,int>> h3
h3[0][0] = 2;
for (int i=0; i<100; i++ ) {
int x=rand()%10;
int y=rand()%10;
int& val = h3[x].emplace(y, 1).first->second;
val *= 2;
}
是的,这有点令人困惑:如果缺少密钥,emplace
会插入指定的值(如果密钥已经存在则不会覆盖),并返回std::pair<iterator, bool>
。
这里,bool告诉你是否插入了你的值,迭代器本身是std::pair<key,val>*
的包装器,因此.first->second
得到了值。
除了更短/更易读之外,这两者也更有效。如果值不存在,则在代码中进行两次查找,但上述两种方法都只进行一次查找。