HOWTO · C++
Wie entferne ich ein Element aus einem Vektor in C++
Dieser Artikel zeigt, wie man ein Element aus einem Vektor in C++ entfernt
Auf dieser Seite
Wenn Sie eine bekannte Position oder einen Bereich entfernen möchten, verwenden Sie std::vector::erase. Für alle Elemente mit einem bestimmten Wert verwenden Sie ab C++20 std::erase; bei älteren C++-Standards kombinieren Sie std::remove und erase im Erase-remove-Idiom. Die Beispiele zeigen, wie sich die Auswahl auf den Vektor auswirkt und wie Iteratoren gültig bleiben.
Ein Element mit std::vector::erase entfernen
std::vector::erase akzeptiert einen Iterator auf ein einzelnes Element oder einen halboffenen Bereich [first, last). Der Bereich umfasst first, aber nicht last. Für den Aufruf mit einem einzelnen Element ist ein gültiger Iterator erforderlich, der auf ein Element zeigt. Die Funktion gibt einen Iterator auf das Element nach dem gelöschten Bereich zurück oder end(), wenn kein weiteres Element folgt.
Dieses vollständige Beispiel entfernt das Element am Index 2 und liest anschließend den zurückgegebenen Iterator aus:
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{10, 20, 30, 40, 50};
auto next = numbers.erase(numbers.begin() + 2);
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << "\nNext value: " << *next << '\n';
}
10 20 40 50
Next value: 40
Beim Löschen werden Iteratoren und Referenzen an oder nach der gelöschten Position ungültig. Aktualisieren oder verwerfen Sie diese Verweise, bevor Sie sie erneut verwenden. Um einen Bereich zu löschen, übergeben Sie den Iterator auf dessen erstes Element und den Iterator direkt hinter dem letzten Element. Der Rückgabewert und die Regeln zur Ungültigkeit sind dieselben. Reicht der gelöschte Bereich bis zum Ende, entspricht der zurückgegebene Iterator numbers.end() und kann nicht dereferenziert werden.
Alle passenden Werte mit std::erase entfernen (C++20)
C++20 ergänzt den Nicht-Member-Überladungsaufruf std::erase für std::vector, der über <vector> deklariert wird. Er entfernt alle Elemente, die dem übergebenen Wert entsprechen, und gibt die Anzahl der entfernten Elemente zurück. Kommt der Wert mehrfach vor, werden alle Vorkommen entfernt. Das ist nützlich, wenn die Auswahl auf einem Wertevergleich beruht. Ältere Sprachstandards bieten diese Überladung nicht; verwenden Sie dafür das Erase-remove-Idiom aus dem nächsten Abschnitt.
Dieses Beispiel verwendet beim Kompilieren mit C++20 std::erase und greift bei einem älteren Standard auf Erase-remove zurück. Beide Varianten entfernen alle Vorkommen von 2 und geben die Anzahl der entfernten Elemente aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 2, 5};
std::size_t removed;
#if __cplusplus >= 202002L
removed = std::erase(numbers, 2);
#else
const auto old_size = numbers.size();
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
removed = old_size - numbers.size();
#endif
std::cout << "Removed: " << removed << "\nRemaining: ";
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Removed: 3
Remaining: 1 3 4 5
Die Überladung von std::erase für std::vector ist ab C++20 verfügbar und gibt die Anzahl der entfernten Elemente zurück. Die Variante für ältere Standards verwendet das Erase-remove-Idiom, das im nächsten Abschnitt erklärt wird.
Passende Werte mit dem Erase-remove-Idiom entfernen
Vor C++20 kombinieren Sie std::remove aus <algorithm> mit der Member-Funktion erase des Vektors. std::remove verschiebt die nicht passenden Werte an den Anfang des beschreibbaren Bereichs und gibt einen Iterator auf dessen neues logisches Ende zurück. Die Größe des Vektors ändert sich dabei nicht: Bis der nachfolgende Bereich gelöscht wird, enthält der Vektor weiterhin dieselbe Anzahl an Elementen. Übergeben Sie den zurückgegebenen Iterator und das ursprüngliche end() des Vektors an erase, um den Container zu verkleinern.
Dieses Beispiel entfernt alle Vorkommen von 2 mit diesem zweistufigen Verfahren:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 5};
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Der an std::remove übergebene Bereich muss beschreibbar sein, da der Algorithmus die beizubehaltenden Werte umordnet. Dass ein Container über konstante Iteratoren einen schreibgeschützten Zugriff ermöglicht, verhindert die Verwendung des Idioms nicht, sofern ein beschreibbarer Iteratorbereich verfügbar ist.
Elemente während einer Schleife sicher löschen
Wenn ein Prädikat oder eine andere Bedingung festlegt, welche Elemente entfernt werden sollen, verwenden Sie eine Iteratorschleife. Weisen Sie nach dem Löschen den von erase zurückgegebenen Iterator zu; erhöhen Sie ihn nur, wenn das aktuelle Element erhalten bleibt. Der gelöschte Iterator ist ungültig. Ihn zu erhöhen oder dereferenzieren wäre daher unsicher.
Dieses Beispiel entfernt gerade Werte und hält dabei den Iterator gültig:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7};
for (auto it = numbers.begin(); it != numbers.end();) {
if (*it % 2 == 0) {
it = numbers.erase(it);
} else {
++it;
}
}
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Verwenden Sie std::erase für das Entfernen gleicher Werte mit C++20, das Erase-remove-Idiom für dieselbe Aufgabe mit älteren Standards und erase in einer Schleife mit dem zurückgegebenen Iterator, wenn die Entfernung von einer Bedingung abhängt. Welche Methode passt, richtet sich danach, ob Sie eine bekannte Position oder einen Bereich, gleiche Werte oder ein während der Schleife ausgewertetes Prädikat als Auswahlkriterium verwenden.