简体   繁体   English

向量.erase错误c2664

[英]vector .erase error c2664

I am trying to iterate through a vector and erase specific items from it. 我正在尝试遍历向量并从中擦除特定项目。 I'm working form the end of the vector down so that I don't mess up the iterator as items are removed, but when I try to compile it's throwing an error. 我正在从向量的末尾开始工作,以便在删除项目时不会弄乱迭代器,但是当我尝试编译时会引发错误。 I looked through some of the other posts with this same error but didn't see anything that applied to my situation, or if there was I didn't catch it, I'm still pretty new to C++ and programming in general. 我浏览了其他一些帖子,但都遇到了同样的错误,但是没有发现任何适用于我的情况的东西,或者如果我没有抓住它,那么我对C ++和一般编程还是很陌生的。 Below is a sample of a simpler code to illustrate my problem. 下面是一个简单的代码示例来说明我的问题。

#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;
} 

any help would be great 任何帮助都会很棒

The most immediate problems in your code are: 您的代码中最直接的问题是:

  • Passing your vector by value , so the original is never modified. 通过value传递矢量,因此永远不会修改原始矢量。
  • Not using erase() properly. 没有正确使用erase() It returns an iterator to the next element in the sequence, which you did not erase (yet). 它返回一个迭代器序列中的下一个元素,你没有删除(还)。 This means if you use iterators and remove an element, you need not (and should not) increment the iterator. 这意味着,如果使用迭代器并删除元素,则无需(也不应)增加迭代器。 An example is forth-coming. 一个例子即将到来。
  • In conjunction with the above, simply, you're not using iterators, and you should be. 结合以上内容,简单地说,您没有使用迭代器,应该使用迭代器。

Your code could do without the function and simply do this: 您的代码可以不使用该函数而只需执行以下操作:

#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;
}

Output 输出量

0 1 2 3 4 5 6 7 8 9 10 
0 1 2 3 4 5 6 

I strongly advise you spend a few days working with iterators. 我强烈建议您花几天的时间来处理迭代器。 Start with something simple (like this example). 从简单的内容开始(例如本示例)。

I am trying to iterate through a vector and erase specific items from it. 我正在尝试遍历向量并从中擦除特定项目。 I'm working form the end of the vector down so that I don't mess up the iterator as items are removed, 我正在从向量的结尾开始工作,以免在删除项目时弄乱迭代器,

In addition to passing by reference instead of by value, instead of writing loops and worry about invalidating iterators, learn to use algorithms, more specifically the erase/remove_if idiom for containers such as vector. 除了按引用而不是按值传递之外,除了编写循环和担心使迭代器无效之外,还要学习使用算法,尤其是对于矢量容器之类的erase/remove_if习惯用法。 It is very easy even for good C++ programmers to make a mistake, which is why the algorithms should be used. 即使是优秀的C ++程序员也很容易犯错误,这就是为什么要使用算法的原因。

Here is a sample of using the idiom (erase/remove_if). 这是使用惯用法的示例(erase / remove_if)。

#include <algorithm>
//...
bool IsGreater(int val) { return val > 6; }
//...
test.erase(std::remove_if(test.begin(), test.end(), IsGreater), test.end());

The remove_if takes the items that satisfy the condition and moves them to the end of the vector. remove_if接受满足条件的项目并将其移动到向量的末尾。 The return value of remove_if() is the iterator that points to the beginning of the moved items. remove_if()的返回值是指向已移动项目开头的迭代器。 Then the erase() takes the items and deletes them from the vector. 然后,delete()接收项目并将其从向量中删除。

The advantage of doing things this way are many, but one of them is that you no longer need to worry about "messing up iterators". 用这种方法做事的好处很多,但是其中之一就是您不再需要担心“搞乱迭代器”。 It is very hard to mess this up -- the one way to mess up is either you provide wrong iterator types (then you will get a syntax error), or your comparison function doesn't work (easily fixed). 搞砸这一点非常困难-搞砸的一种方法是您提供了错误的迭代器类型(那么您将得到语法错误),或者比较功能不起作用(很容易修复)。 But at runtime, there is little to no chance of using invalid iterators. 但是在运行时,几乎没有机会使用无效的迭代器。

The other advantage is that any good C++ programmer can immediately understand what the erase/remove_if() does. 另一个好处是,任何优秀的C ++程序员都可以立即了解Erase / remove_if()的作用。 If I look at your code and you never told us what it did, I would 如果我查看您的代码,但您从未告诉我们它做了什么,我会

1) Have to read it a few times to get what's going on and 1)必须阅读几次才能了解正在发生的事情,并且

2) Have to run it under a debugger to see if it does what I think it does, and do it correctly. 2)必须在调试器下运行它,以查看它是否按照我的想法执行并正确执行。

With the algorithms, I know right away what the code does, and even more important, the code works without having to run it under a debugger. 有了这些算法,我马上就知道代码是做什么的,更重要的是,代码可以工作而不必在调试器下运行。

Note that the sample I provided uses a simple function IsGreater(). 请注意,我提供的示例使用一个简单的函数IsGreater()。 The other ways to write the test function is to use std::greater<> (along with a std::bind1st), using a function object, using a lambda, etc. But I provided probably the easiest way to initially understand what is happening. 编写测试函数的其他方法是使用std :: greater <>(以及std :: bind1st),使用函数对象,使用lambda等。但是我提供了最简单的方法来初步了解什么是发生。

You're passing a copy of your vector to vectorErase , so any changes it makes to its copy have no effect on the original. 您正在将向量的副本传递给vectorErase ,因此对其向量副本vectorErase任何更改均不会影响原始向量。

If you want to modify the vector passed to the function you need to take a reference to the original, rather than a copy. 如果要修改传递给函数的向量,则需要引用原始文件而不是副本。 This is easy - instead of vector<int> test , write vector<int> & test . 这很容易-代替vector<int> test ,编写vector<int> & test

(You are passing iterat by reference, which you don't need. Did you just put the & in the wrong place?) (您通过引用传递了iterat ,您不需要使用它。您是否将&放在错误的位置?)

There are a few problems. 有一些问题。 First, there's the fact that you must pass the vector by reference to affect the original. 首先,有一个事实是必须通过引用传递矢量才能影响原始矢量。

int vectorErase(vector<int>&, int );

Then there's the problem of the second loop: 然后是第二个循环的问题:

    for(int i=10;i>=0;i--)
    {
        vectorErase(test, i);
        cout<<test[i] << ' ';
    }

And finally the function itself with the proper use of erase : 最后,通过正确使用erase功能本身:

int vectorErase(vector<int> &test, int iterat)
{
    if(test[iterat]>6)
    {
        test.erase(test.begin()+iterat);
    }
    return 0;
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM