Namensräume
Varianten
Aktionen

std::unique

Von cppreference.com
< cpp‎ | algorithm
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
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 [firstlast) und gibt einen Iterator nach dem Ende 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) Dasselbe wie (1,3), aber ausgeführt gemäß policy.
Diese Überladungen nehmen an der Auflösungsauflösung teil, nur wenn alle folgenden Bedingungen erfüllt sind

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)

Inhalt

[bearbeiten] Erklärung

Das Entfernen geschieht durch Verschieben der Elemente im Bereich so, dass die nicht zu entfernenden Elemente am Anfang des Bereichs erscheinen.

  • Das Verschieben erfolgt durch Kopierzuweisung(bis C++11)Verschiebungszuweisung(seit C++11).
  • Der Entfernungsvorgang ist stabil: Die relative Reihenfolge der nicht zu entfernenden Elemente bleibt erhalten.
  • Die zugrunde liegende Sequenz von [firstlast) wird durch den Entfernungsvorgang nicht verkürzt. Sei result der zurückgegebene Iterator
  • Jedes Element von [resultlast) hat einen gültigen, aber unbestimmten Zustand, da die Verschiebungszuweisung Elemente eliminieren kann, indem sie von Elementen verschiebt, die ursprünglich in diesem Bereich lagen.
(seit C++11)

[bearbeiten] Parameter

first, last - das Iteratorenpaar, das den Bereich der zu verarbeitenden Elemente definiert
policy - die Ausführungsrichtlinie, die verwendet werden soll
p - binäre Prädikatfunktion, die ​true zurückgibt, wenn die Elemente als gleich behandelt werden sollen.

Die Signatur der Prädikatfunktion sollte äquivalent zur folgenden sein:

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

Obwohl die Signatur nicht zwingend const & haben muss, darf die Funktion die ihr übergebenen Objekte nicht modifizieren und muss alle Werte vom Typ (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 gleichbedeutend mit 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 von dereferenziertem ForwardIt muss die Anforderungen von MoveAssignable erfüllen.

[bearbeiten] Rückgabewert

Ein ForwardIt auf das neue Ende des Bereichs.

[bearbeiten] Komplexität

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

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

[bearbeiten] Ausnahmen

Die Überladungen mit einem Template-Parameter namens ExecutionPolicy berichten Fehler wie folgt

  • Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und ExecutionPolicy eine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsabhängig.
  • Wenn dem Algorithmus der Speicher zur Neuzuweisung fehlt, wird std::bad_alloc ausgelöst.

[bearbeiten] 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;
}

[bearbeiten] Hinweise

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

[bearbeiten] Beispiel

#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
    // a vector containing several duplicate elements
    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);
 
    // remove consecutive (adjacent) duplicates
    auto last = std::unique(v.begin(), v.end());
    // v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate
    v.erase(last, v.end());
    print(2);
 
    // sort followed by unique, to remove all duplicates
    std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
    print(3);
 
    last = std::unique(v.begin(), v.end());
    // v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate
    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

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 202 C++98 war das Verhalten unklar, wenn die Elemente
mit einer Nicht-Äquivalenzrelation verglichen werden
Das Verhalten ist
in diesem Fall nicht definiert.

[bearbeiten] Siehe auch

Findet die ersten beiden benachbarten Elemente, die gleich sind (oder eine gegebene Bedingung erfüllen)
(Funktionstempelat) [edit]
Erstellt eine Kopie eines Bereichs von Elementen, die keine aufeinanderfolgenden Duplikate enthält
(Funktionstemplate) [edit]
entfernt Elemente, die bestimmte Kriterien erfüllen
(Funktionstemplate) [edit]
entfernt aufeinanderfolgende doppelte Elemente
(öffentliche Memberfunktion von std::list<T,Allocator>) [bearbeiten]
entfernt aufeinanderfolgende doppelte Elemente
(öffentliche Memberfunktion von std::forward_list<T,Allocator>) [bearbeiten]
Entfernt aufeinanderfolgende doppelte Elemente in einem Bereich
(Algorithmus-Funktionsobjekt)[edit]