std:: remove, std:: remove_if
|
Definiert in Header
<algorithm>
|
||
| (1) | ||
|
template
<
class
ForwardIt,
class
T
>
ForwardIt remove ( ForwardIt first, ForwardIt last, const T & value ) ; |
(constexpr seit C++20)
(bis C++26) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
>
|
(seit C++26) | |
| (2) | ||
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
T
>
ForwardIt remove
(
ExecutionPolicy
&&
policy,
|
(seit C++17)
(bis C++26) |
|
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
|
(seit C++26) | |
|
template
<
class
ForwardIt,
class
UnaryPred
>
ForwardIt remove_if ( ForwardIt first, ForwardIt last, UnaryPred p ) ; |
(3) | (constexpr seit C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt,
class
UnaryPred
>
ForwardIt remove_if
(
ExecutionPolicy
&&
policy,
|
(4) | (seit C++17) |
Entfernt alle Elemente, die bestimmte Kriterien erfüllen, aus dem Bereich
[
first
,
last
)
und gibt einen Iterator zurück, der über das neue Ende des Bereichs hinauszeigt.
|
std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> ist true . |
(bis C++20) |
|
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> ist true . |
(seit C++20) |
|
Wenn der
Werttyp
von
|
(bis C++11) |
|
Wenn der Typ von * first nicht MoveAssignable ist, ist das Verhalten undefiniert. |
(seit C++11) |
Inhaltsverzeichnis |
Erklärung
Das Entfernen erfolgt durch Verschieben der Elemente im Bereich in einer Weise, dass die nicht zu entfernenden Elemente am Anfang des Bereichs erscheinen.
- Das Verschieben erfolgt durch copy assignment (until C++11) move assignment (since C++11) .
- Der Entfernungsvorgang ist stabil: Die relative Reihenfolge der nicht zu entfernenden Elemente bleibt gleich.
-
Die zugrundeliegende Sequenz von
[first,last)wird durch den Entfernungsvorgang nicht verkürzt. Mit result als zurückgegebenem Iterator:
-
-
Alle Iteratoren in
[result,last)bleiben dereferenzierbar .
-
Alle Iteratoren in
|
(seit C++11) |
Parameter
| first, last | - | das Paar von Iteratoren, das den Bereich der zu verarbeitenden Elemente definiert |
| value | - | der Wert der zu entfernenden Elemente |
| policy | - | die zu verwendende Ausführungsrichtlinie |
| p | - |
unäres Prädikat, das
true
zurückgibt, wenn das Element entfernt werden soll.
Der Ausdruck
p
(
v
)
muss für jedes Argument
|
| Typanforderungen | ||
-
ForwardIt
muss die Anforderungen von
LegacyForwardIterator
erfüllen.
|
||
-
UnaryPredicate
muss die Anforderungen von
Predicate
erfüllen.
|
||
Rückgabewert
Past-the-end-Iterator für den neuen Wertebereich (falls dies nicht end ist, dann zeigt es auf einen unspezifizierten Wert, und dasselbe gilt für Iteratoren zu allen Werten zwischen diesem Iterator und end ).
Komplexität
Gegeben N als std:: distance ( first, last ) :
Ausnahmen
Die Überladungen mit einem Template-Parameter namens
ExecutionPolicy
melden Fehler wie folgt:
-
Wenn die Ausführung einer als Teil des Algorithmus aufgerufenen Funktion eine Exception wirft und
ExecutionPolicyeiner der Standard-Policies ist, wird std::terminate aufgerufen. Für jede andereExecutionPolicyist das Verhalten implementierungsdefiniert. - Wenn der Algorithmus keinen Speicher allokieren kann, wird std::bad_alloc geworfen.
Mögliche Implementierung
| remove (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> ForwardIt remove(ForwardIt first, ForwardIt last, const T& value) { first = std::find(first, last, value); if (first != last) for (ForwardIt i = first; ++i != last;) if (!(*i == value)) *first++ = std::move(*i); return first; } |
| remove_if (3) |
template<class ForwardIt, class UnaryPred> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p) { first = std::find_if(first, last, p); if (first != last) for (ForwardIt i = first; ++i != last;) if (!p(*i)) *first++ = std::move(*i); return first; } |
Hinweise
Ein Aufruf von
remove
wird typischerweise von einem Aufruf der
erase
-Memberfunktion eines Containers gefolgt, um Elemente tatsächlich aus dem Container zu entfernen. Diese beiden Aufrufe zusammen bilden das sogenannte
Erase-Remove-Idiom
.
|
Derselbe Effekt kann auch durch die folgenden Nicht-Mitgliedsfunktionen erreicht werden:
|
(since C++20) |
Die ähnlich benannten Container- Memberfunktionen list::remove , list::remove_if , forward_list::remove und forward_list::remove_if löschen die entfernten Elemente.
Diese Algorithmen können nicht mit assoziativen Containern wie std::set und std::map verwendet werden, da ihre Iteratortypen nicht auf MoveAssignable -Typen dereferenzieren (die Schlüssel in diesen Containern sind nicht veränderbar).
Die Standardbibliothek definiert auch eine Überladung von std::remove in <cstdio> , die einen const char * akzeptiert und zum Löschen von Dateien verwendet wird.
Da
std::remove
den
value
als Referenz nimmt, kann es unerwartetes Verhalten verursachen, wenn es sich um eine Referenz auf ein Element des Bereichs
[
first
,
last
)
handelt.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | Listeninitialisierung für Algorithmen ( 1,2 ) |
Beispiel
Der folgende Code entfernt alle Leerzeichen aus einem String, indem alle Nicht-Leerzeichen nach links verschoben und anschließend die überflüssigen Zeichen gelöscht werden. Dies ist ein Beispiel für das erase-remove idiom .
#include <algorithm> #include <cassert> #include <cctype> #include <complex> #include <iomanip> #include <iostream> #include <string> #include <string_view> #include <vector> int main() { std::string str1{"Quick Red Dog"}; std::cout << "1) " << std::quoted(str1) << '\n'; const auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' '); std::cout << "2) " << std::quoted(str1) << '\n'; // Die Leerzeichen werden nur logisch aus dem String entfernt. // Beachten Sie, dass wir eine View verwenden, der ursprüngliche String wurde noch nicht verkleinert: std::cout << "3) " << std::quoted(std::string_view(str1.begin(), noSpaceEnd)) << ", size: " << str1.size() << '\n'; str1.erase(noSpaceEnd, str1.end()); // Die Leerzeichen wurden physisch aus dem String entfernt. std::cout << "4) " << std::quoted(str1) << ", size: " << str1.size() << '\n'; std::string str2 = "Jumped\n Over\tA\vLazy \t Fox\r\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x) { return std::isspace(x); }), str2.end()); std::cout << "5) " << std::quoted(str2) << '\n'; std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}}; #ifdef __cpp_lib_algorithm_default_value_type nums.erase(std::remove(nums.begin(), nums.end(), {1, 3}), nums.end()); #else nums.erase(std::remove(nums.begin(), nums.end(), std::complex<double>{1, 3}), nums.end()); #endif assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}})); }
Ausgabe:
1) "Quick Red Dog" 2) "QuickRedDog Dog" 3) "QuickRedDog", size: 15 4) "QuickRedDog", size: 11 5) "JumpedOverALazyFox"
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| LWG 283 | C++98 |
T
musste
EqualityComparable
sein, aber
der Werttyp von
ForwardIt
ist nicht immer
T
|
forderte stattdessen, dass der Werttyp von
ForwardIt
CopyAssignable sein muss |
Siehe auch
|
kopiert einen Bereich von Elementen unter Auslassung derjenigen, die bestimmte Kriterien erfüllen
(Funktions-Template) |
|
|
entfernt aufeinanderfolgende doppelte Elemente in einem Bereich
(Funktions-Template) |
|
|
(C++20)
(C++20)
|
entfernt Elemente, die bestimmte Kriterien erfüllen
(Algorithmus-Funktionsobjekt) |