Search code examples
c++iterator

C++ Iterator ( Next )


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
       }

Solution

  • 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?