2

I am erasing element from the C++ multimap using following code which is running perfectly under Linux, but throwing expression set/map is not incrementable on Windows.

void delete_entries(multimap<int, pair<int, int> > &m, int i, int j) {
    // This function deletes entries from multimap where box number == i and Ball index ==j

    multimap<int, pair<int, int> > ::iterator it = m.begin();
    while (it != m.end()) {
        if ((*it).second.first == i || (*it).second.second == j)
            m.erase(it);
        it++;
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

3 Answers3

2
while (it != m.end()) {
    if ((*it).second.first == i || (*it).second.second == j)
        m.erase(it);
    it++;   //if the previous condition holds true, 'it' is invalidated
}

An erased iterator becomes invalidated. And incrementing an invalidated iterator is Undefined behavior.

Undefined behavior means that even if it seemingly works, there are no more guarantees to the behavior of your entire program. (this applies to the seemingly working one in linux too; you should be really happy that it crashed on MSVC)

For the correct way to erase, see the other answers here and this question: How to remove from a map while iterating it?

Community
  • 1
  • 1
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
2

Since C++11, erase returns the iterator following the last removed element.

void delete_entries(multimap<int, pair<int, int> > &m, int i, int j) {
// this function deletes entries from multimap where box number == i and Ball index ==j 

  multimap<int, pair<int, int> > ::iterator it = m.begin();
  while (it != m.end()) {
    if ((*it).second.first == i || (*it).second.second == j)
      it = m.erase(it);
    else
      it++;
  }
}
1

The iterator becomes invalid after erase. Since C++11, you can do:

while (it != m.end()) {
    if ((*it).second.first == i || (*it).second.second == j)
        it = m.erase(it);
    else
        it++;
}
rocambille
  • 15,398
  • 12
  • 50
  • 68