C ++ STL矢量擦除

时间:2013-05-28 18:52:41

标签: c++ vector stl

问题在于,当我运行该功能时,它会在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);
        }
    }
}

3 个答案:

答案 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;
}