[C++] Listeniterator nicht inkrementierbar


Answers

Beachten Sie, dass iter->arrivalTime == 0 zweimal inkrementiert: einmal vor der Elemententfernung und noch einmal am Ende der Schleife.

Wenn das zu entfernende Element das letzte Element in der Liste ist, funktioniert dies offensichtlich nicht korrekt. Ich wage zu sagen, dass es selbst in VS2003 nie richtig funktioniert hat, aber VS2005 warnt Sie besser darüber. :-)

Denken Sie daran, es ist undefiniertes Verhalten, um end() zu wiederholen. Es kann absolut alles passieren, wie zB Programmabsturz oder (in diesem Fall) eine Fehlermeldung.

Question

Ich habe ein altes Projekt, das mit Visual Studio 2003 erstellt wurde und ich habe es vor kurzem mit vs2005 neu kompiliert. Zur Laufzeit erhalte ich jedoch folgende Fehlermeldung:

Listeniterator nicht inkrementierbar

Ich habe das Programm auf diese Funktion zurückgeführt:

void InputQueue::update()
{
    list<PCB>::iterator iter;
    list<PCB>::iterator iterTemp;
    for(iter = begin(); iter != end(); iter++)
    {
        if(iter->arrivalTime == 0)
        {           
            ReadyQueue::getInstance()->add(*iter);
            iterTemp = iter;
            iter++;
            erase(iterTemp);
        }
    }
}

Ich bin kein C ++ - Experte und das ist so weit, wie der VS-Debugger mich hat. Könnte mir jemand erklären, was das Problem ist?

Vielen Dank




Darf ich einen einfacheren Algorithmus vorschlagen?

Die freie Funktion std::remove_if kann verwendet werden, um Ihre Liste in 2 zu partitionieren, Elemente, die mit dem Prädikat übereinstimmen oder nicht übereinstimmen (dh arrivalTime == 0). Es gibt den Iterator zurück, der die Bereiche trennt. Sie können dann ReadyQueue::getInstance()->add(subrange_begin, subrange_end) , ReadyQueue::getInstance()->add(subrange_begin, subrange_end) aufrufen (Sie haben diese Überladung, oder?) Und den Unterbereich anschließend löschen.

Nur ein Fall, in dem Sie STL-Algorithmen verwenden können, anstatt Ihre eigenen Schleifen zu schreiben.




Das ist nur eine Nebensache, aber eine wichtige.

Ich vermute, du erbst von einem std::ist<PCB> . Ich muss sagen: Vererbung zur Wiederverwendung von Funktionalität hat sich für mich oft nicht bewährt. Aber da Sie das Projekt auch "erben", gibt es nicht viel zu tun ...




Die Grundursache ist "list.erase ()", die den Iterator ändert. Das richtige Schreiben für die "for" -Schleife:

   for (list<CMessage*>::iterator it=que.begin(); it!=que.end(); ++it)
   {
    if(m_type == (*it)->m_type)
    {
        delete *it;
        it=que.erase(it); //"list.erase()" will change the iterator!!!
        if(it==que.end()) break; //Check again!!!
        //still has side effect here. --it?
    }
   }

Aber es hat immer noch Nebeneffekt, also wird Mark's while Lösung die Beste sein.