为什么在迭代时从向量中擦除元素会导致分段错误(核心已转储)?
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 中擦除元素的正确方法是什么?
正如评论所说,i
是 unsigned
,因此 i >= 0
始终为真。当 i
变得小于 0
它实际上变成了一个大的正数,然后用 i
索引到向量中会调用未定义的行为。
从向量中删除元素的正确方法是使用erase-remove-if习惯用法:
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i) {
return i > 2; }), vec.end());
以下生成了我在大型程序中遇到的问题。
#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 中擦除元素的正确方法是什么?
正如评论所说,i
是 unsigned
,因此 i >= 0
始终为真。当 i
变得小于 0
它实际上变成了一个大的正数,然后用 i
索引到向量中会调用未定义的行为。
从向量中删除元素的正确方法是使用erase-remove-if习惯用法:
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i) {
return i > 2; }), vec.end());