为什么在迭代时从向量中擦除元素会导致分段错误(核心已转储)?

Why erasing element from vector while iterating causes Segmentation fault (core dumped)?

以下生成了我在大型程序中遇到的问题。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec{1, 2, 3, 4, 5};

    for (unsigned i = vec.size() - 1; i >= 0; --i) {
        if (vec[i] > 2) vec.erase(vec.begin() + i);
        else cout << vec[i] << "  ";
    }
    cout << endl;


    return 0;
}

这导致 Segmentation fault (core dumped)

调试了一下,发现改代码如下,"solves"问题所在。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec{1, 2, 3, 4, 5};

    for (unsigned i = vec.size() - 1; i >= 1; --i) {
        if (vec[i] > 2) vec.erase(vec.begin() + i);
        else cout << vec[i] << "  ";
    }
    if (vec[0] > 2) vec.erase(vec.begin());
    else cout << vec[0] << "  ";
    cout << endl;


    return 0;
}

这是打印我期望得到的结果。

2 1

不就是第一个程序里的for循环吗?我只是将向量开头的条件移到循环外!

还有像这样迭代时从 vector 中擦除元素的正确方法是什么?

正如评论所说,iunsigned,因此 i >= 0 始终为真。当 i 变得小于 0 它实际上变成了一个大的正数,然后用 i 索引到向量中会调用未定义的行为。

从向量中删除元素的正确方法是使用erase-remove-if习惯用法:

vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i) {
            return i > 2; }), vec.end());