【问题标题】:vector .erase error c2664矢量 .erase 错误 c2664
【发布时间】:2014-04-11 19:07:51
【问题描述】:

我正在尝试遍历向量并从中删除特定项目。我正在从向量的末尾向下工作,以免在删除项目时弄乱迭代器,但是当我尝试编译时会抛出错误。我浏览了其他一些具有相同错误的帖子,但没有看到任何适用于我的情况的内容,或者如果我没有发现它,我对 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;
} 

任何帮助都会很棒

【问题讨论】:

  • 发布错误消息并指定有错误的代码行。
  • 很多事情都错了...首先,int&amp; 不是iterator,(这是erase() 的参数)!
  • 对于初学者,您需要修复 main 中的第二个循环。应该是 for(int i=10;i>=0;i--)

标签: c++ vector compiler-errors


【解决方案1】:

您的代码中最直接的问题是:

  • 通过传递你的向量,所以原件永远不会被修改。
  • 没有正确使用erase()。它返回一个迭代器,指向序列中的 next 元素,您已经 not 擦除了它(还)。这意味着如果您使用迭代器并删除一个元素,则不需要(也不应该)增加迭代器。一个例子即将出现。
  • 结合上述内容,简单地说,您没有使用迭代器,您应该使用。

您的代码可以不使用该函数,只需执行以下操作:

#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 

我强烈建议您花几天时间使用迭代器。从简单的事情开始(比如这个例子)。

【讨论】:

    【解决方案2】:

    我正在尝试遍历向量并从中删除特定项目。我正在从向量的末尾向下工作,以免在删除项目时弄乱迭代器,

    除了按引用而不是按值传递之外,不要编写循环并担心使迭代器失效,学习使用算法,更具体地说,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(以及 std::bind1st)、使用函数对象、使用 lambda 等。但我提供了可能是最初了解什么是最简单的方法正在发生。

    【讨论】:

    • 感谢您对算法的建议,我会研究它们,但到目前为止我还没有使用它们或有任何曝光。
    • @James - 我编辑了我的答案,补充说优秀的 C++ 程序员很容易把它弄得一团糟,即使是从容器中删除项目这样看似简单的事情。这就是使用算法的原因。
    • 此答案中的合理建议。如果有办法我可以放弃我的选中状态并将其放在这里,我会的。 Uptick 是我能提供的最好的。
    【解决方案3】:

    您将矢量的副本传递给vectorErase,因此它对其副本所做的任何更改都不会影响原始文件。

    如果你想修改传递给函数的向量,你需要引用原始的,而不是副本。这很简单——不要写vector&lt;int&gt; test,而是写vector&lt;int&gt; &amp; test

    (您通过引用传递iterat,您不需要。您只是将&amp; 放在错误的位置吗?)

    【讨论】:

      【解决方案4】:

      有几个问题。首先,您必须通过引用传递向量才能影响原始向量。

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

      【讨论】:

      • 感谢您解释要更改的内容和原因,我做了您所说的更改,但我现在收到以下错误消息。 错误 1 ​​错误 C3867: 'std::vector<_ty>::begin': 函数调用缺少参数列表;使用 '&std::vector<_ty>::begin' 创建指向成员的指针 我也会发布代码,但无法在评论中正确格式化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2011-12-22
      • 2014-10-04
      相关资源
      最近更新 更多