为什么我们需要在从 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 ?
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 对正确做法有更好的答案。
我有以下程序。我需要理解为什么我们在使用擦除方法时需要递减指针? 还有没有更好的方法不会造成这样的混乱?
#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 ?
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 对正确做法有更好的答案。