向量迭代器擦除给我一个运行时错误

Vector iterator erase giving me a runtime error?

本文关键字:一个 运行时错误 迭代器 擦除 向量      更新时间:2023-10-16

所以我在我的类中有一个方法,这个类应该做的是,检查我在。h文件中的向量是否有double low &double high,然后删除它们,最后返回删除了多少个"空格"

所以我尝试了一些事情,我总是得到运行时错误,它似乎是在for循环,但我不能弄清楚为什么。

这是我尝试过的,

一开始我只是试着按照我觉得它会起作用的方式去做:

int datastorage::eraseDataPointsBetween(double low,double high) 
{
    int antal = 0;
    for (vector<double>::iterator i = data_.begin(); i !=data_.end();i++)
    {
        if (*i >=low && *i <=high)
        {
            data_.erase(i);
            antal++;
        }
    }
    return antal;
}

但后来我试着做了一些调试,我可以看到它实际上没有意义,因为当某些内容被删除时,它仍然会增加(所以如果我们删除"空间2",它实际上会在下一次检查空间4(因为位置3在擦除后变为位置2))

所以我试着把它改成

int datastorage::eraseDataPointsBetween(double low,double high) 
{
    int antal = 0;
    for (vector<double>::iterator i = data_.begin(); i !=data_.end();)
    {
        if (*i >=low && *i <=high)
        {
            data_.erase(i);
            antal++;
        }
        else 
            i++;
    }
    return antal;
}

当我不删除空格时,它只增加i(因此,如果我删除"space 2",它将检查新的"space 2"下一次运行)

这也给了我一个语法错误expression: vector iterators incompatible

希望你能帮助我,因为我很迷路

vector::erase使迭代器无效,因此不能在调用擦除后使用它。你应该这样从vector中删除:

int datastorage::eraseDataPointsBetween( double low, double high)  {
  int antal = 0;
  for( vector<double>::iterator i = data_.begin(); i !=data_.end())
  {  
     if( (*i >= low) && (*i <= high))
     {
        i = data_.erase( i); // new (valid) iterator is returned
        ++antal;
     }
     else
     {
        ++i;
     }
   return antal;
}

您应该使用remove_if()和erase。这比自己编写循环更稳定的原因很简单——使用无效迭代器不会遇到麻烦。

#include <algorithm>
#include <vector>
struct IsBetween
{
   double low, high;
   IsBetween(double l, double h) : low(l), high(h) {}
   bool operator()(double d) const { return d >= low && d <= high; }
};
void datastorage::eraseDataPointsBetween(double low,double high) 
{
   std::vector<double>::iterator it = std::remove_if(data.begin(), data.end(), IsBetween(low, high));
   data.erase(it, data.end());
}

没有循环,注意remove_if()与函数对象IsBetween的使用。

底线是,当你在容器上循环时,你应该尽量减少写循环来擦除容器中的项。有remove_if()、remove()、partition()等,它们将您想要关注的数据移动到容器的一端。

在循环过程中,你会看到很多擦除迭代器的答案,这似乎是安全的,有多少人会记住返回的规则,或者更简单地说,写错了循环?(即使是经验丰富的c++程序员也可能在第一次切割时错误地编写循环)。所以使用算法来为你做这些工作。

对于remove_if(),"坏"数据被移到末尾,现在您可以轻松地删除它们。