我有代码看起来像这样:
for (std::list- ::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++
:"List iterator not incrementable".我尝试了一些替代品,它们没有在for语句中增加,但我无法得到任何工作.
当你走std :: list时,删除项目的最佳方法是什么?
您必须首先递增迭代器(使用i ++),然后删除前一个元素(例如,使用i ++中返回的值).您可以将代码更改为while循环,如下所示:
std::list- ::iterator i = items.begin(); while (i != items.end()) { bool isActive = (*i)->update(); if (!isActive) { items.erase(i++); // alternatively, i = items.erase(i); } else { other_code_involving(*i); ++i; } }
你想做:
i= items.erase(i);
这将正确地更新迭代器以指向您删除的迭代器后的位置.
您需要结合Kristo的答案和MSN:
// Note: Using the pre-increment operator is preferred for iterators because // there can be a performance gain. // // Note: As long as you are iterating from beginning to end, without inserting // along the way you can safely save end once; otherwise get it at the // top of each loop. std::list< item * >::iterator iter = items.begin(); std::list< item * >::iterator end = items.end(); while (iter != end) { item * pItem = *iter; if (pItem->update() == true) { other_code_involving(pItem); ++iter; } else { // BTW, who is deleting pItem, a.k.a. (*iter)? iter = items.erase(iter); } }
当然,效率最高的SuperCool®STLsavy就是这样的:
// This implementation of update executes other_code_involving(Item *) if // this instance needs updating. // // This method returns true if this still needs future updates. // bool Item::update(void) { if (m_needsUpdates == true) { m_needsUpdates = other_code_involving(this); } return (m_needsUpdates); } // This call does everything the previous loop did!!! (Including the fact // that it isn't deleting the items that are erased!) items.remove_if(std::not1(std::mem_fun(&Item::update)));
使用std :: remove_if算法.
编辑: 使用集合应该像:1.准备集合.2.流程收集.
如果你不混合这些步骤,生活会更容易.
的std ::的remove_if.或list :: remove_if(如果你知道你使用list而不是TCollection)
的std :: for_each的
这是一个使用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);