我正在尝试迭代向量并从中删除特定项目。我正在向下生成向量的末尾,以便在删除项目时不会弄乱迭代器,但是当我尝试编译它时会抛出错误。我查看了一些其他帖子,但同样的错误,但没有看到任何适用于我的情况,或者如果我没有抓住它,我仍然是C ++和编程的新手。下面是一个简单代码的示例,用于说明我的问题。
#include <iostream>
#include <vector>
using namespace std;
int vectorErase(vector<int>, int &);
int main()
{
vector<int> test;
for(int i=0; i<11;i++)
{
test.push_back(i);
cout<<test[i];
}
for(int i=10;i<=0;i--)
{
vectorErase(test, i);
cout<<test[i];
}
system("pause");
return 0;
}
int vectorErase(vector<int> test, int &iterat)
{
if(test[iterat]>6)
{
test.erase(iterat);
}
return 0;
}
任何帮助都会很棒
答案 0 :(得分:2)
代码中最直接的问题是:
erase()
。它返回一个迭代器到序列中的 next 元素,你做了 not erase(还)。这意味着如果使用迭代器并删除元素,则不需要(也不应该)递增迭代器。一个例子即将到来。您的代码可以不使用该功能,只需执行此操作:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> test;
for(int i=0; i<11;i++)
{
cout << i << ' ';
test.push_back(i);
}
cout << '\n';
for(auto it = test.begin(); it != test.end();)
{
if (*it > 6)
it = test.erase(it);
else
{
cout << *it << ' ';
++it;
}
}
cout << '\n';
return 0;
}
<强>输出强>
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6
我强烈建议您花几天时间使用迭代器。从简单的东西开始(比如这个例子)。
答案 1 :(得分:1)
我正在尝试迭代向量并从中删除特定项目。我在向量的末尾工作,以便在删除项目时不会弄乱迭代器,
除了通过引用而不是通过值传递,而不是编写循环并担心使迭代器无效,学习使用算法,更具体地说是容器(如vector)的erase/remove_if
惯用法。即使是优秀的C ++程序员也很容易犯错,这就是为什么应该使用算法的原因。
以下是使用成语(erase / remove_if)的示例。
#include <algorithm>
//...
bool IsGreater(int val) { return val > 6; }
//...
test.erase(std::remove_if(test.begin(), test.end(), IsGreater), test.end());
remove_if接受满足条件的项目并将它们移动到向量的末尾。 remove_if()的返回值是指向移动项的开头的迭代器。然后erase()获取项目并从向量中删除它们。
以这种方式做事的好处很多,但其中一个就是你不再需要担心“弄乱迭代器”。很难弄清楚这一点 - 弄乱的一种方法是你提供错误的迭代器类型(然后你会得到一个语法错误),或者你的比较函数不起作用(很容易修复)。但是在运行时,几乎没有机会使用无效的迭代器。
另一个优点是任何优秀的C ++程序员都可以立即理解erase / remove_if()的作用。如果我查看你的代码并且你从未告诉我们它做了什么,我会
1)必须阅读几次才能了解正在发生的事情
2)必须在调试器下运行它以查看它是否符合我的想法,并且正确执行。
使用这些算法,我立刻知道代码的作用,更重要的是,代码无需在调试器下运行即可运行。
请注意,我提供的示例使用了一个简单的函数IsGreater()。编写测试函数的其他方法是使用std :: greater&lt;&gt; (以及std :: bind1st),使用函数对象,使用lambda等。但我提供了最简单的方法来初步了解正在发生的事情。
答案 2 :(得分:0)
您已将矢量副本传递给vectorErase
,因此对其副本所做的任何更改都不会影响原件。
如果要修改传递给函数的向量,则需要引用原始对象而不是副本。这很容易 - 而不是vector<int> test
,请写vector<int> & test
。
(您正在通过引用传递iterat
,这是您不需要的。您刚刚将&
放在错误的位置吗?)
答案 3 :(得分:0)
有一些问题。首先,事实是你必须通过引用传递向量来影响原始。
int vectorErase(vector<int>&, int );
然后是第二个循环的问题:
for(int i=10;i>=0;i--)
{
vectorErase(test, i);
cout<<test[i] << ' ';
}
最后,函数本身正确使用erase
:
int vectorErase(vector<int> &test, int iterat)
{
if(test[iterat]>6)
{
test.erase(test.begin()+iterat);
}
return 0;
}