Domanda

How can i delete all objects which are works finished

I using the following code but get list iterator not incrementable

How can I remove it without deleting it

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
    }
}
È stato utile?

Soluzione

erase returns an iterator

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

Altri suggerimenti

You can make use of the fact that erase returns a new iterator, as described in other answers here. For performance-critical code, that might be the best solution. But personally, I would favor splitting the loop into separate processing and removal steps for readability and clarity:

// 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();
});

If you don't want to use remove_if, some alternatives are:

  • Copy all objects you want to keep into a new list, then std::swap it with your current list
  • Use a temporary list toBeRemoved, and add all objects that should be removed to that. When you're finished iterating over the actual list, iterate toBeRemoved and call myList.erase for each element

Some workaround..

increment the number of objects from the list that has WorkFnished. then after the loop. if the accumulator match the list size, clear it.

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

If you use erase you have to assign it back to the iterator. In this case, we have to take care of the incrementing ourselves depending if the current element was erased or not.

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::list::erase

Return: An iterator pointing to the new location of the element that followed the last element erased by the function call. This is the container end if the operation erased the last element in the sequence.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top