Kürzlich habe ich beim Lesen eines Buches zufällig ein Detail entdeckt: den Löschvorgang von Vektoren. Für diesen Löschvorgang weiß jeder, dass dieser Löschvorgang zwei Formen hat: (1) Löschen eines einzelnen Elements, der Parameter ist eine Iteratorvariable, (2) Löschen eines Intervallelements, die Parameter sind Anfang und Ende. Die Details sind die spezifischen Dinge, die passieren, wenn ein einzelnes Element gelöscht wird.
Beispiel: Es gibt einen Vektor, der wie folgt initialisiert wird: vector
Normalerweise wird der Code so geschrieben:
#include <vector> #include <iostream> int main() { std::vector<int> va{ 1,2,3,4,4,5,6 }; std::vector<int> vb(va); for (auto i = va.begin();i != va.end(); i++) { if (*i == 4) { i = va.erase(i); } } for (auto i : va) { std::cout << i << " "; } return 0; }
Auf den ersten Blick ist nichts falsch, aber das Ergebnis ist unerwartet
Warum ist das Ergebnis so? Nach sorgfältiger Überlegung stellt sich heraus, dass beim Löschen ein Fehler aufgetreten ist. Wenn die if-Bedingung erfüllt ist, führt der Vektor einen Löschvorgang aus und löscht die Elemente im Vektor, die die Bedingungen erfüllen Führt den Löschvorgang aus, stellt der zurückgegebene Wert die nächste Position des aktuell gelöschten Iterators dar. Wenn die Schleife dann erneut wiederholt wird, bewegt sich der Iterator um eine Position zurück, wodurch dasselbe Element gelöscht wird.
Anbei die korrekte Schreibweise:
#include <vector> #include <iostream> int main() { std::vector<int> va{ 1,2,3,4,4,5,6 }; std::vector<int> vb(va); auto iter = vb.begin(); while(iter!=vb.end()) { if (iter != vb.end()) { if (*iter == 4) { iter = vb.erase(iter); } else { iter++; } } } for (auto j : vb) { std::cout << j << " "; } return 0; }
#include <vector> #include <iostream> int main() { std::vector<int> va{ 1,2,3,4,4,5,6 }; for (auto i = va.begin();i != va.end(); ) { if (*i == 4) { i = va.erase(i); } else { i++; } } for (auto i : va) { std::cout << i << " "; } return 0; }