I have this code that i am using to get an idea of how C Next iterator work on key value map that has a struct. I can not think of how: iter->val happens to be 1 when struct value is 0 for key "test" next->val happens to be 0
Can someone help me understand this please.
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <unordered_map>
#include <set>
#include<unordered_set>
using namespace std;
struct test {
int val;
unordered_set<string> st;
};
int main()
{
list <test> tst;
unordered_map < string , list<test>::iterator > m;
m["test"] = tst.insert(tst.begin() , {0 , {"test"}});
auto iter = m["test"] , next = iter ;
cout << iter->val << endl; // prints 1 . Not sure how
cout << next->val << endl; // prints 0 not sure how also
}
CodePudding user response:
cout << iter->val
makes your program have undefined behavior. After iter
it will be pointing at tst.end()
and dereferencing end()
is "illegal".
cout << next->val
would be ok though since next
is pointing at the one element that exists in tst
.
CodePudding user response:
You first create a struct test with val=0 and st={"test"}. That gets inserted into the list tst
, so that has one entry now. The return value is an iterator pointing at the new element and is put into m["test"]. So your unordered map has one entry "test" that is an iterator of tst
. And now the fun begins...
auto iter = m["test"];
iter
becomes a reference to the iterator pointing at the first element of tst
.
auto next = iter ;
Now two things happen: First next
gets a copy of iter
and now also points at the first element of tst
. Secondly iter
gets incremented (post increment) to point at the next item in the list. Since there are no more it now points to tst::end()
.
Now lets answer your question of what happens on the output:
cout << iter->val << endl; // prints 1 . Not sure how
This is undefined behavior. You are not allowed to operator->() end()
. It points to somewhere in memory and randomly that contains 0 so you get 0. Lucky your cat didn't get pregnant.
cout << next->val << endl; // prints 0 not sure how also
Since in practice a little UB does no harm your program continues and accesses next
. Since next
points to the first element of tst
that gets accessed. The first element of tst
is {.val = 0; .st={"test"}}
so next->val
outputs 0.
Are you sure you want a unordered_map of iterators instead of an unordered_map of list?