Namespaces
Variants

std::unique

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z. B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgenändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und zugehörige Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Definiert in Header <algorithm>
template< class ForwardIt >
ForwardIt unique( ForwardIt first, ForwardIt last );
(1) (constexpr seit C++20)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt unique( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last );
(2) (seit C++17)
template< class ForwardIt, class BinaryPred >
ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p );
(3) (constexpr seit C++20)
template< class ExecutionPolicy,
          class ForwardIt, class BinaryPred >
ForwardIt unique( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, BinaryPred p );
(4) (seit C++17)

Entfernt alle bis auf das erste Element aus jeder aufeinanderfolgenden Gruppe äquivalenter Elemente aus dem Bereich [first, last) und gibt einen Iterator für das neue Ende des Bereichs zurück.

1) Elemente werden mit operator== verglichen.
Wenn operator== keine Äquivalenzrelation herstellt, ist das Verhalten undefiniert.
3) Elemente werden mit dem gegebenen binären Prädikat p verglichen.
Wenn p keine Äquivalenzrelation herstellt, ist das Verhalten undefiniert.
2,4) Gleich wie (1,3), aber ausgeführt gemäß policy.
Diese Überladungen nehmen nur an der Überladungsauflösung teil, wenn der Wert des folgenden Ausdrucks true ist:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(bis C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(seit C++20)

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:
  • Jedes Element von [ result , last ) hat einen gültigen, aber unspezifizierten Zustand, da Move-Zuweisung Elemente entfernen kann, indem von Elementen bewegt wird, die ursprünglich in diesem Bereich waren.
(seit C++11)

Parameter

first, last - das Paar von Iteratoren, das den Bereich der zu verarbeitenden Elemente definiert
policy - die zu verwendende Ausführungsrichtlinie
p - binäres Prädikat, das ​ true zurückgibt, wenn die Elemente als gleich behandelt werden sollen.

Die Signatur der Prädikatfunktion sollte äquivalent zu Folgendem sein:

bool pred ( const Type1 & a, const Type2 & b ) ;

Obwohl die Signatur nicht const & benötigt, darf die Funktion die übergebenen Objekte nicht modifizieren und muss alle Werte des Typs (möglicherweise const) Type1 und Type2 unabhängig von der Wertkategorie akzeptieren können (daher ist Type1 & nicht erlaubt , ebenso wenig wie Type1 , es sei denn, für Type1 ist eine Verschiebung äquivalent zu einer Kopie (seit C++11) ).
Die Typen Type1 und Type2 müssen so beschaffen sein, dass ein Objekt vom Typ ForwardIt dereferenziert und dann implizit in beide konvertiert werden kann. ​

Typanforderungen
-
ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen.
-
Der Typ des dereferenzierten ForwardIt muss die Anforderungen von MoveAssignable erfüllen.

Rückgabewert

Ein ForwardIt zum neuen Ende des Bereichs.

Komplexität

Gegeben N als std:: distance ( first, last ) :

1,2) Genau max(0,N-1) Vergleiche unter Verwendung von operator == .
3,4) Genau max(0,N-1) Anwendungen des Prädikats p .

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 ExecutionPolicy einer der Standard-Policies ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsdefiniert.
  • Wenn der Algorithmus keinen Speicher allokieren kann, wird std::bad_alloc geworfen.

Mögliche Implementierung

Siehe auch die Implementierungen in libstdc++ , libc++ , und MSVC STL .

unique (1)
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
    if (first == last)
        return last;
    ForwardIt result = first;
    while (++first != last)
        if (!(*result == *first) && ++result != first)
            *result = std::move(*first);
    return ++result;
}
unique (3)
template<class ForwardIt, class BinaryPredicate>
ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p)
{
    if (first == last)
        return last;
    ForwardIt result = first;
    while (++first != last)
        if (!p(*result, *first) && ++result != first)
            *result = std::move(*first);
    return ++result;
}

Hinweise

Ein Aufruf von unique wird typischerweise gefolgt von einem Aufruf der erase -Memberfunktion eines Containers, um tatsächlich Elemente aus dem Container zu entfernen.

Beispiel

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    // ein Vektor mit mehreren doppelten Elementen
    std::vector<int> v{1, 2, 1, 1, 3, 3, 3, 4, 5, 4};
    auto print = [&](int id)
    {
        std::cout << "@" << id << ": ";
        for (int i : v)
            std::cout << i << ' ';
        std::cout << '\n';
    };
    print(1);
    // entferne aufeinanderfolgende (benachbarte) Duplikate
    auto last = std::unique(v.begin(), v.end());
    // v enthält nun {1 2 1 3 4 5 4 x x x}, wobei 'x' undefiniert ist
    v.erase(last, v.end());
    print(2);
    // sortieren gefolgt von unique, um alle Duplikate zu entfernen
    std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
    print(3);
    last = std::unique(v.begin(), v.end());
    // v enthält nun {1 2 3 4 5 x x}, wobei 'x' undefiniert ist
    v.erase(last, v.end());
    print(4);
}

Ausgabe:

@1: 1 2 1 1 3 3 3 4 5 4
@2: 1 2 1 3 4 5 4
@3: 1 1 2 3 4 4 5
@4: 1 2 3 4 5

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 202 C++98 das Verhalten war unklar, wenn die Elemente
mit einer Nicht-Äquivalenzrelation verglichen werden
das Verhalten ist
in diesem Fall undefiniert

Siehe auch

findet die ersten beiden benachbarten Elemente, die gleich sind (oder ein gegebenes Prädikat erfüllen)
(Funktions-Template & Algorithmus-Funktionsobjekt)
erstellt eine Kopie eines Bereichs von Elementen, die keine aufeinanderfolgenden Duplikate enthält
(Funktions-Template & Algorithmus-Funktionsobjekt)
entfernt Elemente, die bestimmte Kriterien erfüllen
(Funktions-Template & Algorithmus-Funktionsobjekt)
entfernt aufeinanderfolgende doppelte Elemente
(öffentliche Mitgliedsfunktion von std::list<T,Allocator>)
entfernt aufeinanderfolgende doppelte Elemente
(öffentliche Mitgliedsfunktion von std::forward_list<T,Allocator>)
entfernt aufeinanderfolgende doppelte Elemente in einem Bereich
(Algorithmus-Funktionsobjekt)