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

时间:2014-03-28 22:51:09

标签: c++ vector

所以我在我的类中有一个方法,这个类应该做的是,检查我.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(所以如果我删除“空格2”,它将检查新的“空格2”下一次运行)

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

希望你能帮忙,因为我很丢失

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

你应该使用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(),&#34; bad&#34;数据移动到最后,您现在可以轻松删除它们。