在循环中移除列表中的对象

C++ Remove Objects in List at Loop

本文关键字:对象 列表 循环      更新时间:2023-10-16

如何删除所有已完成的对象

我使用下面的代码但是得到list迭代器不可递增

如何在不删除它的情况下删除它

list<A*> myList;
for(list<A*>::iterator it = myList.begin(); it !=myList.end(); ++it ){
    (*it )->DoSomething();
    if((*it )->WorksFnished()){
        //myList.erase(it );    <- It's works but I get exception after the loop
        //myList.remove(*it );  <- It's works but I get exception after the loop
    }
}

erase返回一个迭代器

list<A*> myList;
list<A*>::iterator it = myList.begin();
while( it != myList.end() ) {
    (*it)->DoSomething();
    if( (*it)->WorksFnished() ) {
        it = myList.erase(it);
    } else {
        ++it;
    }
}

您可以利用erase返回一个新的迭代器这一事实,如这里的其他答案所述。对于性能关键型代码,这可能是最好的解决方案。但就我个人而言,为了可读性和清晰度,我更倾向于将循环分成单独的处理和删除步骤:

// Assumes C++ 11 compatible compiler
list<A*> myList;
// Processing
for(const auto* each : myList){
    each->DoSomething();
}
// Deletion
myList.remove_if([](A* each) {
    return each->WorksFnished();
});

如果你不想使用remove_if,一些替代方案是:

  • 复制所有你想要的对象保持到一个新的列表,然后std::swap它与你的当前列表
  • 使用临时列表toBeRemoved,并添加所有应该删除的对象。当您完成对实际列表的迭代时,迭代toBeRemoved并为每个元素
  • 调用myList.erase

一些变通办法…

增加列表中包含WorkFnished的对象的个数。然后在循环之后。如果累加器与列表大小匹配,则将其清除。

size_t nFinished = 0;
list<A*> myList;
for(list<A*>::iterator it = myList.begin(); it !=myList.end(); ++it ){
    (*it )->DoSomething();
    if((*it )->WorksFnished()){
         nFinished++;
    }
}
if (nFinished == myList.size())
{
     myList.clear();
}

如果使用erase,则必须将其重新赋值给迭代器。在这种情况下,我们必须根据当前元素是否被删除来处理自增操作。

list<A*> myList;
for (auto it = myList.begin(); it != myList.end(); )
{
    (*it)->DoSomething();
    if( (*it)->WorksFnished() ) {
        it = myList.erase(it);    // Sets it to the next element
    } else {
        ++it;        // Increments it since no erasing
    }
}

std::列表::擦除

Return:指向被函数调用擦除的最后一个元素后面元素的新位置的迭代器。如果该操作删除了序列中的最后一个元素,则为容器端。