简体   繁体   English

C ++ STL矢量擦除

[英]C++ STL vector erase

The problem is that when I run the function it crashes at the erase part and I cant figure out why. 问题是,当我运行该功能时,它会在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);
        }
    }
}

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. 此外,您不希望在擦除后增加i ,否则您将在删除后跳过该元素。 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. 或者看看“erase-remove”习语的其他答案,这是一种很好的,也许是更有效的方法,可以避免这种容易出错的逻辑。

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. 看起来你应该使用STL算法std::remove_if而不是这个,这可以方便地避免其他回答者已经指出的问题。 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. 请注意,这优于您的解决方案,因为它相对于向量中的元素数量需要线性时间,而for / erase解决方案需要二次时间。

i goes beyond the size of the vector. i超越了矢量的大小。 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. 由于erase调用,向量的大小变小,但是直到保存的大小,如果有已擦除的项目,则大于实际大小。

This is why erase returns an iterator, it is a valid iterator to the element next to the erased one: 这就是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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM