Reputation: 118
The problem is that when I run the function it crashes at the erase
part and I cant figure out why.
void Grupa::del() {
int size = studenti.size();
for (int i=0; i<size; i++) {
if (studenti[i].materia1<5 && studenti[i].materia2<5 && studenti[i].materia3<5) {
studenti.erase(studenti.begin()+i);
}
}
}
Upvotes: 2
Views: 242
Reputation: 254731
When you erase an element, the vector gets smaller; but you're still using the original size, and falling off the end. Also, you don't want to increment i
after erasing, otherwise you'll skip the element after the erased one. So you want something like:
for (size_t i = 0;
i != studenti.size(); // don't hoist out of the loop
/* don't increment here */)
{
if (...) {
studenti.erase(studenti.begin()+i);
} else {
++i;
}
}
Or see other answers for the "erase-remove" idiom, which is a nice, and perhaps more efficient, way of avoiding this kind of error-prone logic.
Upvotes: 12
Reputation: 2089
i
goes beyond the size of the vector. Due to the erase
calls the size of the vector gets smaller, but you go until the saved size, which is greater than the actual if there were erased items.
This is why erase
returns an iterator, it is a valid iterator to the element next to the erased one:
for (auto it = studenti.begin(); it != studenti.end();) {
if (it->materia1<5 && it->materia2<5 && it->materia3<5)
it = studenti.erase(it);
else
++it;
}
Upvotes: 0
Reputation: 106609
It looks like you should be using an STL algorithm, std::remove_if
, instead of this, which conveniently avoids the problems other answerers have pointed out already. Consider this instead:
studenti.erase(std::remove_if(studenti.cbegin(), studenti.cend(), [](Student const& currentStudent) {
return currentStudent.materia1<5 && currentStudent.materia2<5 && currentStudent.materia3<5;
}), studenti.cend());
Note that this has the advantage over your solution in that it takes linear time relative to the number of elements in the vector, while the for/erase solution takes quadratic time.
Upvotes: 6