Bhawan
Bhawan

Reputation: 2491

iterator invalidation in map C++

I have a sample program in which I am trying to see how the iterator invalidates while deleting the elements from a map.

The program is here:

#include <iostream>
#include <map>

using namespace std;

int main(int argc, char *argv[])
{

    map<int, int> myMap;

    myMap.insert(pair<int, int>(0, 2));    
    myMap.insert(pair<int, int>(1, 4));    
    myMap.insert(pair<int, int>(3, 18));    
    myMap.insert(pair<int, int>(2, 20));    

    map<int, int>::iterator it; 

    for(it = myMap.begin(); it != myMap.end(); ++it) 
    {   
        myMap.erase(it);  // erasing the element pointed at by iterator

        cout << it->first << endl; // iterator is invalid here 
    }   
    return 0;
}

The problem is that I am getting output is:

0
1
2
3  

Why the iterator is not invalidating and giving me wrong results. Any help would be highly appreciated.

Documentation of C++ STL maps says that: References and iterators to the erased elements are invalidated. Other references and iterators are not affected.

Upvotes: 3

Views: 2139

Answers (3)

Aconcagua
Aconcagua

Reputation: 25526

Using an invalidated iterator is undefined behaviour. In such case, anything could happen.

Why do you see the values? The iterator contains a pointer to some piece of memory, by pure accident, this memory has not yet been returned to the system and has not yet been overwritten. This is why you still can see the already "dead" values.

It does not change anything, it remains undefined behaviour, and the next time you run the program, the memory page the map element resided in could already have been returned to the OS again and you get an access violation (segmentation fault)...

Upvotes: 4

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136266

There are no run-time checks for invalid iterators by default.

You can enable the debug checks for invalid iterators with -D_GLIBCXX_DEBUG for GNU C++ standard library. That produces the following run-time error:

iterator "this" @ 0x0x7fff9f3d7060 {
type = N11__gnu_debug14_Safe_iteratorISt17_Rb_tree_iteratorISt4pairIKiiEENSt7__debug3mapIiiSt4lessIiESaIS4_EEEEE (mutable iterator);
  state = singular;
  references sequence with type `NSt7__debug3mapIiiSt4lessIiESaISt4pairIKiiEEEE' @ 0x0x7fff9f3d7150
}

For other standard libraries check the documentation.

Upvotes: 2

Rinat Veliakhmedov
Rinat Veliakhmedov

Reputation: 1039

Invalidated iterator does not mean that its internal data was erased. Sometimes like in this case the invalidated iterator may hold a valid reference to the next item. However, using it like this is Undefined Behavior and it likely to cause some problems in your application.

Upvotes: 2

Related Questions