Different behavior observed upon doing erase(iterator) on vector and map

41 views Asked by At

A simple std::vector

std::vector<int> integers;
integers.push_back(10);
integers.push_back(11);    
cout  << "Before: " << integers.size();  //prints 2

I tried using 3 different versions of code to erase each element one by one C++5.1 and C++14

Version 1:

for( std::vector<int>::iterator it = integers.begin() ; it != integers.end() ; )
{
  cout << "\nVal: " << *it;
  it = integers.erase(it); 
}

cout << "\nAfter: " << integers.size(); 

Output: [Expected]

Before: 2
Val: 10
Val: 11
After: 0

Version 2 in C++14:

for( std::vector<int>::iterator it1, it = integers.begin() ; it != integers.end() ; )
{
    cout << "\nVal: " << *it;
    it1 = std::next(it);
    integers.erase(it);
    it = it1;
}

Output: [Unexpected]

Before: 2
Val: 10
After: 1

While for std::map, version 2 works as expected:

int main() {
    std::map<int, int> m;
    m.insert(make_pair(10, 11));
    m.insert(make_pair(12, 13));
    cout  << "Before: " << m.size();

    for( std::map<int, int>::iterator it1, it = m.begin() ; it != m.end() ; )
    {
        cout << "\nVal:  " << it->first << ", " << it->second;
        it1 = std::next(it);
        m.erase(it);
        it = it1;
    }
    cout << "\nAfter: " << m.size();
    return 0;
}

Outputs:

Before: 2
Val:  10, 11
Val:  12, 13
After: 0

Even this works :

for( std::map<int, int>::iterator it1, it = m.begin() ; it != m.end() ; )
{
    cout << "\nVal:  " << it->first << ", " << it->second;
    m.erase(it++);
}

Why version 2 works on std::map but not on std::vector?

1

There are 1 answers

4
Vlad from Moscow On BEST ANSWER

The difference is that std::vector iterators are invalidated after erasing an element while for associative containers (23.2.4 Associative container)

9 The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.