1

My applications requires to iterate over a vector and delete certain elements which doesnt satisfy the requirements. Which is the most correct way? I believe the following way is incorrect.Reason: I am getting segmentation fault.

std::vector<ObjectX> vec1;
//Fill in vec1
std::vector<ObjectX>::iterator itVec1 = vec1.begin();

for(;itVec1 != vec1.end(); ++itVec1) {
   if (Oracle(*itVec1)) vec1.erase(itVec1);
}
letsBeePolite
  • 2,183
  • 1
  • 22
  • 37
  • When you're using `erase`, it invalidates iterators and references at or after the point of the erase, including the end() iterator. – Andreas DM Mar 31 '16 at 23:11
  • I usually iterate it in reverse order and use index access instead of vector iterator – Asier Sánchez Rodríguez Mar 31 '16 at 23:13
  • I feel like the two most frequent C++ questions I see: how do I get numbers out of `std::string`s and why is my program segfaulting when invalidating my iterator. – erip Mar 31 '16 at 23:17

2 Answers2

4

When you call

vec1.erase(itVec1);

you invalidate itVec1. After that, ++itVec1 is not right. It leads to undefined behavior. You need to change your code a little bit.

for( ; itVec1 != vec1.end(); ) {
   if (Oracle(*itVec1))
   {
      itVec1 = vec1.erase(itVec1);
   }
   else
   {
      ++itVec1;
   }
}

You can remove all the boiler plate code by using the Erase-Remove Idiom:

vec1.erase(std::remove_if(vec1.begin(), vec1.end(), Oracle), vec1.end());
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

You could just put the correct items into a new vector.