【问题标题】:Erase all even numbers from vector using find_if [duplicate]使用 find_if 从向量中删除所有偶数 [重复]
【发布时间】:2018-05-28 20:06:38
【问题描述】:
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include <iomanip>

using namespace std;

bool isEven(int n)
{ 
    return n%2 == 0;
}

int main()
{
    srand(time(NULL));

    vector<int> myVec;

    for(int i = 0; i < 20; i++)
    {
        myVec.push_back(rand() % 100);
    }   
    while(1)
    {   
          vector<int>::iterator q = std::find_if(myVec.begin(), myVec.end(), isEven);
          cout << *q << endl;
          if(q == myVec.end())
          {   
             myVec.erase(q);
             break;
          }   
          else
             myVec.erase(q);        
      }

    return 0;
}

此代码给出分段错误。上面的代码是使用 find_if 和擦除函数从向量中删除所有偶数

请帮忙。任何帮助将不胜感激。

编辑:我已经对其进行了编辑以确保迭代器始终有效。

仍然出现分段错误。

【问题讨论】:

  • 不能“它”是 nullptr 吗? *它没有空检查!
  • 既然有remove_if,为什么还要使用find_if
  • 您正在擦除第一个 if 分支中的结束迭代器 q
  • cmets 和答案的重点是编写循环不是完成这项工作所必需的。如果这项工作听起来像是以前做过数百万次的事情,那么很可能有一种算法可以完成这项工作,并且该算法是std::remove_if

标签: c++ stl


【解决方案1】:

使用erase(it); 函数时,迭代器会发生变化,因此您需要再次将迭代器设置为擦除函数返回的新迭代器。

在您的代码中,您正在检查结尾if(q == myVec.end()),然后使用擦除这将引发错误,因为.end() 不指向数据,并且能够从迭代器需要的向量中擦除一个项目有效。因此,通过将if(q == myVec.end()) 更改为if(q == (myVec.end()-1)),它将允许您删除最后一个元素,以防成为一对。

【讨论】:

    【解决方案2】:

    std::vector::erase 使擦除点之前和之后的所有迭代器无效。你不能继续使用那个迭代器,不能增加它,用它来访问向量,甚至把它和end()比较。

    要使用的正确算法是std:remove_if。不像名字所暗示的那样,它只会将向量的所有偶数项“移到后面”,而不会使任何迭代器失效。它将一个迭代器返回到该子范围的开头,然后您可以将其提供给适当的erase 重载(接受一对迭代器的那个)。

    这在代码中被大量使用,甚至被命名为“擦除删除习语”。

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 2021-05-13
      • 2019-12-31
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多