2016-12-01 4 views
1

Ich schrieb dieses einfache Testprogramm. Aber ich kann nicht verstehen, was hier passiert. Weil es eine seltsame Sache in der Ausgabe ist:Was passiert am Ende mit dem Iterator, wenn ein Listenelement gelöscht wird?

std::list<std::pair<double,double>> l; 
l.push_back({0.3,0.9}); 
l.push_back({-0.3,0.5}); 
l.push_back({0.3,0.7}); 
l.push_back({1.2,1.83}); 


for(auto it=l.begin(); it!=l.end(); ++it){ 
    double lx= it->first + 0.01; 
    double ly= it->second + 0.01; 

    it->first = lx; 
    it->second = ly; 

    if(lx < 0.0 || lx > 1.0 || ly < 0.0 || ly > 1.0){ 
    it = l.erase(it); 
} 

Wenn ich die Liste zu drucken, erhalte ich:

0.32, 0.92 
0.31, 0.71 

Warum funktioniert der Iterator auf das erste Element geht zurück (zweimal +0,1)?

+1

Das '== 0' im if ist überflüssig, in der Tat ist das ganze if unbrauchbar, weil das' it! = End() 'dafür sorgen wird. Und ich bin mir nicht sicher, warum du gesagt hast, dass das erste Element zweimal da ist? Es sieht so aus, als ob Sie Elemente an Position 1 und 3 entfernen und daher die Elemente 0 und 2 drucken. – Borgleader

+0

Danke für die Antwort. Ja, es druckt Element 0 und 2, aber es addiert 0,1 zweimal am ersten Element. Ich kann nicht verstehen, warum: Es sollte (0,31, 0,91) und (0,31,0,71) – Susliks

+0

sein. Ein typisches Muster dafür ist das * Erase-Remove-Idiom * mit 'I.Erase (Std: : remove_if (...), l.end()) '. – ArchbishopOfBanterbury

Antwort

7
it=list.erase(it); 

Dies löscht das Element bei it. Es gibt dann die Iteratorposition zurück, nachdem das gelöschte Element war.

Wenn Ihre for Schleife eine Iteration beendet, geht es it über ++ prüft dann, ob es end() entspricht.

Ihre Schleife beide überspringt das Element nach jedem gelöscht. Nicht gut. Und wenn es das letzte Element löscht, fährt es mit dem End-Iterator fort, was illegal ist.

Entfernen Sie ++it aus dem for Loop-Header. Am unteren Ende der Schleife, entweder itoder löschen bei it, nicht beides noch keine.

Das seltsame Druckverhalten ist auf UB zurückzuführen. Sie erhöhen Daten an Position 0. Sie erhöhen Daten an Position 1 und löschen sie anschließend. Sie überspringen Position 2. Sie erhöhen Daten an Position 3 und löschen sie anschließend. Sie gehen über den Enditerator hinaus (undefiniertes Verhalten). Dann passieren zufällige Dinge, die zufällig den Datenstandort 0 und 2 wieder inkrementieren. Als eine Vermutung, ++ am Ende Iterator geschieht Schleife auf das erste Element in Ihrem Fall (das ist nicht garantiert, aber mit UB kann alles passieren). Die zweite Schleife läuft dann wie normal, inkrementiert die Daten an den zwei Elementen und löscht nichts.

Verwandte Themen