I have this 2 codes,
Code 1
#include<bits/stdc .h>
using namespace std;
int main()
{
unordered_map<int,int>m;
int nums[]={1,1,3,4,5};
for(auto x:nums)
{
m[x] ;
}
for(auto x:m)
{
cout<<x.first<<" "<<m[x.first]<<endl;
}
return 0;
}
Code 2
#include<bits/stdc .h>
using namespace std;
int main()
{
unordered_map<int,int>m;
int nums[]={1,1,3,4,5}; int k=2;
for(auto x:nums)
{
m[x] ;
}
for(auto x:m)
{
cout<<x.first<<" "<<m[x.first k]<<endl;
}
return 0;
}
The output of the first code is
5 1
4 1
1 2
3 1
But the output of the second code is
5 0
4 0
5 0
7 0
I am not getting why the output of the 2nd code is like this, shouldn't it be like
5 0 //5 is the index and m[5 2]=0 hence 0
4 0
1 1 //since m[1 2]=1
3 1
......................................................................................................................................................................................................................
CodePudding user response:
When you do m[x.first k]
, you're modifying m
when x.first k
is not already in m
. According to en.cppreference.com:
If an insertion occurs and results in a rehashing of the container, all iterators are invalidated. [...]
If this occurs, you're invalidating iterators while iterating the map since for (auto x: m)
is just a hidden way of iterating using iterators. Thus, your code has undefined behavior (you're using invalidated iterators), hence what you are seeing (and also why other people might see something different).
CodePudding user response:
operator[], on a map or unordered_map, has the potential to change the container, because (as you're relying on) when you call it with a key which isn't already present, it immediately adds it with a default-constructed value. As such, it's not safe to evaluate m[foo]
while looping over m
unless you're certain that foo
is already present.
I'm not sure what this code is trying to do, but assuming it's just trying to print 0 when the value for the shifted key isn't present, you could do unordered_map::find
directly on that shifted key and check whether the returned iterator is valid, and if not, print 0 instead.