问题在于,当我运行该功能时,它会在erase
部分崩溃,我无法找出原因。
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);
}
}
}
答案 0 :(得分:12)
擦除元素时,向量变小;但你仍然使用原始尺寸,并从最后掉下来。此外,您不希望在擦除后增加i
,否则您将在删除后跳过该元素。所以你需要这样的东西:
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;
}
}
或者看看“擦除 - 删除”这个习惯用法的其他答案,这是避免这种容易出错的逻辑的一种很好的,也许是更有效的方法。
答案 1 :(得分:6)
看起来你应该使用STL算法std::remove_if
而不是这个,这可以方便地避免其他回答者已经指出的问题。请考虑一下:
studenti.erase(std::remove_if(studenti.cbegin(), studenti.cend(), [](Student const& currentStudent) {
return currentStudent.materia1<5 && currentStudent.materia2<5 && currentStudent.materia3<5;
}), studenti.cend());
请注意,这比您的解决方案更有优势,因为它相对于向量中的元素数量需要线性时间,而for / erase解决方案需要二次时间。
答案 2 :(得分:0)
i
超出了向量的大小。由于erase
调用,向量的大小变小,但是直到保存的大小,如果有已删除的项目,则大于实际大小。
这就是erase
返回迭代器的原因,它是擦除的元素旁边元素的有效迭代器:
for (auto it = studenti.begin(); it != studenti.end();) {
if (it->materia1<5 && it->materia2<5 && it->materia3<5)
it = studenti.erase(it);
else
++it;
}