我有这样的代码:

for (std::list<item*>::iterator i=items.begin();i!=items.end();i++)
{
    bool isActive = (*i)->update();
    //if (!isActive) 
    //  items.remove(*i); 
    //else
       other_code_involving(*i);
}
items.remove_if(CheckItemNotActive);

我想在更新后立即删除不活跃的项目,以避免再次浏览列表。但是如果我添加注释掉的行,当我到达i++时,我得到一个错误:“列表迭代器不可递增”。我尝试了一些在for语句中不增加的替代方法,但我不能让任何东西工作。

什么是最好的方法来删除项目,因为你正在走std::列表?


当前回答

Kristo回答的循环版本的替代方案。

你会损失一些效率,你在删除的时候会向后再向前,但作为交换,你可以在循环范围内声明迭代器,代码看起来更干净一些。选择什么取决于当前的优先事项。

我知道这个答案完全过时了……

typedef std::list<item*>::iterator item_iterator;

for(item_iterator i = items.begin(); i != items.end(); ++i)
{
    bool isActive = (*i)->update();

    if (!isActive)
    {
        items.erase(i--); 
    }
    else
    {
        other_code_involving(*i);
    }
}

其他回答

我想分享一下我的方法。此方法还允许在迭代期间将元素插入到列表的后面

#include <iostream>
#include <list>

int main(int argc, char **argv) {
  std::list<int> d;
  for (int i = 0; i < 12; ++i) {
    d.push_back(i);
  }

  auto it = d.begin();
  int nelem = d.size(); // number of current elements
  for (int ielem = 0; ielem < nelem; ++ielem) {
    auto &i = *it;
    if (i % 2 == 0) {
      it = d.erase(it);
    } else {
      if (i % 3 == 0) {
        d.push_back(3*i);
      }
      ++it;
    }
  }

  for (auto i : d) {
      std::cout << i << ", ";
  }
  std::cout << std::endl;
  // result should be: 1, 3, 5, 7, 9, 11, 9, 27,
  return 0;
}

下面是一个使用for循环的示例,该循环迭代列表,并在遍历列表期间删除项时增加或重新验证迭代器。

for(auto i = items.begin(); i != items.end();)
{
    if(bool isActive = (*i)->update())
    {
        other_code_involving(*i);
        ++i;

    }
    else
    {
        i = items.erase(i);

    }

}

items.remove_if(CheckItemNotActive);

删除只会使指向被删除元素的迭代器失效。

所以在这种情况下,删除*i后,i是无效的,你不能对它做增量操作。

你能做的是首先保存要删除的元素的迭代器,然后增加迭代器,然后删除保存的迭代器。

向后迭代避免了在要遍历的剩余元素上擦除一个元素的效果:

typedef list<item*> list_t;
for ( list_t::iterator it = items.end() ; it != items.begin() ; ) {
    --it;
    bool remove = <determine whether to remove>
    if ( remove ) {
        items.erase( it );
    }
}

PS:看看这个,例如,关于向后迭代。

PS2:我没有彻底测试它是否处理好擦除元素在结束。

如果你把std::list想象成一个队列,那么你可以对所有你想保留的项进行出队列和入队列,但只对你想删除的项进行出队列(而不是入队列)。下面是一个例子,我想从包含数字1-10的列表中删除5…

std::list<int> myList;

int size = myList.size(); // The size needs to be saved to iterate through the whole thing

for (int i = 0; i < size; ++i)
{
    int val = myList.back()
    myList.pop_back() // dequeue
    if (val != 5)
    {
         myList.push_front(val) // enqueue if not 5
    }
}

myList现在只有数字1-4和6-10。