为什么我们需要在从 vector 中删除时递减迭代器?

Why do we need to decrement iterator while deleting from vector?

我有以下程序。我需要理解为什么我们在使用擦除方法时需要递减指针? 还有没有更好的方法不会造成这样的混乱?

#include <iostream>
#include <vector>
using namespace std;
 

int main()
{
    vector<int> myvector{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
    for (auto i = myvector.begin(); i != myvector.end(); ++i) {
        if (*i % 2 == 0) {
            myvector.erase(i);
            i--;// why do we need to decrement ?
        }
    }
 
    // Printing the vector
    for (auto it = myvector.begin(); it != myvector.end(); ++it)
        cout << ' ' << *it;
    return 0;
}

I need to understand why do we need to decrement pointer when we use erase method?

你不需要,也不应该。正确的做法是使用 erase 的 return 值。目前你的程序有未定义的行为,因为你正在修改一个无效的迭代器。

for (auto i = myvector.begin(); i != myvector.end();) {
    if (*i % 2 == 0) {
        i = myvector.erase(i);
    } else {
        ++i;
    }
}

Also is there any better way which does not create a such confusion ?

是的,std::remove_if

auto is_even = [](int i){ return (i % 2) == 0; };
auto last = std::remove_if(myvector.begin(), myvector.end(), is_even);
myvector.erase(last, myvector.end());

Caleth 的回答很好,但我要补充一些信息:

for (auto i = myvector.begin(); i != myvector.end(); ++i) {
    if (*i % 2 == 0) {
        myvector.erase(i);
        i--;// why do we need to decrement ?
    }
}

这是你的代码。对于我的解释,让我们相信迭代器只是一个索引(一个 int)。不是,但它有助于理解。

假设 myvector 包含整数 0..10 并且您删除了 4。一旦您这样做:

0 1 2 3 5 6 7 8 9 10

现在,想象一下您的循环。您到达 for 循环的底部并递增 i——它现在有 5,但是您跳过检查旧的 myvector[5]——现在存储在 myvector[4] 中——是否适合你的 if 语句.

另一种写法:

for (auto i = myvector.begin(); i != myvector.end(); ) { 如果 (...) ... 别的 { ++我; } }

也就是说,如果不删除,则只能递增迭代器。这样可以避免跳过您删除的项目之后的项目(因为它移到了被删除的人的位置)。

但是,这是错误的做法,Caleth 对正确做法有更好的答案。