在迭代时通过列表擦除项目时遇到问题

时间:2013-10-01 14:10:20

标签: c++

好的,我有一个我正在迭代的STL参考列表。该功能有三个等效部分。该函数将wstring作为参数,并运行相应的if语句。我已经将代码减少到一个if语句来尝试让它工作。

所以,我检查一下作为参数传递了什么。然后我检查ClassItem是否是某种类型的动物。如果是,我检查它是否饿了,并从列表中删除它。我现在只是想避免seg故障,似乎无法做到。

    list<ClassItem *>::iterator i = Items.begin();

    while(i != Items.end())    
    {
        if(!AnimalType.compare(L"tiger"))
        {
           if((*i)->IsAnimalType(L"tiger"))
           {
              if((*i)->IsHungry())
              {
                  i = Items.erase(i);

              }
           }
           else
           {
              ++i;
           }
        }
      // I have tried removing this
      else
      {
        i++;
      }
    }

我的印象是当我调用erase时当前迭代器无效。所以,如果我擦除一个元素,我将返回下一个有效的迭代器。我哪里错了?

编辑:谢谢你的快速帮助。问题已得到解决。我已经使用了phresnel的解决方案并且工作得非常好。

3 个答案:

答案 0 :(得分:3)

使用std::list::remove_if和合适的谓词最好。这完全避免了手动循环,减少了错误的范围,并帮助删除或至少你本地化了问题的根源,因为只要你的谓词可以依赖这个习语是正确的。

bool badAnimal(ClassItem * item) 
{
  // return true if animal is to be removed 
 }

Items.remove_if(badAnimal);

答案 1 :(得分:1)

我认为这里没有潜在的段错误。反正:


有(恕我直言)两个可能的问题:

if(!AnimalType.compare(L"tiger"))

这看起来很可疑。什么是AnimalType?如果if(!AnimalType.compare(L"tiger"))本身,您是否真的希望AnimalType的值在迭代期间发生变化?

在任何情况下,它看起来像一个读取,因此不应该写。它看起来不变,因此不应该改变。


然后:

       if((*i)->IsAnimalType(L"tiger"))
       {
          if((*i)->IsHungry())
          {
              i = Items.erase(i);
          }
          // NO ITERATION IN CASE OF NOT HUNGRY.
          // ONCE TRAPPED HERE, YOU HAVE AN INFINITE LOOP,
          // EXCEPT AnimalType.compare(L"tiger") DOES SOMETHING
          // NON-SANE.
       }
       else
       {
          ++i;
       }

这最好是:

       if((*i)->IsAnimalType(L"tiger") && (*i)->IsHungry())
       {
          i = Items.erase(i);
       }
       else
       {
          ++i;
       }

然而,更好的方法是使用标准算法去除元素。

答案 2 :(得分:0)

您可能想要添加

continue;
擦除后