Namespaces
Variants

std:: unique

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Определено в заголовке <algorithm>
template < class ForwardIt >
ForwardIt unique ( ForwardIt first, ForwardIt last ) ;
(1) (constexpr начиная с C++20)
template < class ExecutionPolicy, class ForwardIt >

ForwardIt unique ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last ) ;
(2) (начиная с C++17)
template < class ForwardIt, class BinaryPred >
ForwardIt unique ( ForwardIt first, ForwardIt last, BinaryPred p ) ;
(3) (constexpr начиная с C++20)
template < class ExecutionPolicy,

class ForwardIt, class BinaryPred >
ForwardIt unique ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last, BinaryPred p ) ;
(4) (начиная с C++17)

Удаляет все элементы, кроме первого, из каждой последовательной группы эквивалентных элементов в диапазоне [ first , last ) и возвращает итератор, указывающий за новый конец диапазона.

1) Элементы сравниваются с помощью operator == .
Если operator == не устанавливает отношение эквивалентности , поведение не определено.
3) Элементы сравниваются с использованием заданного бинарного предиката p .
Если p не задает отношение эквивалентности, поведение не определено.
2,4) То же, что и (1,3) , но выполняется в соответствии с policy .
Эти перегрузки участвуют в разрешении перегрузки только при выполнении всех следующих условий:

std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> является true .

(до C++20)

std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> является true .

(начиная с C++20)

Содержание

Объяснение

Удаление осуществляется путем сдвига элементов в диапазоне таким образом, что элементы, которые не должны быть удалены, появляются в начале диапазона.

  • Сдвиг выполняется с помощью copy assignment (until C++11) move assignment (since C++11) .
  • Операция удаления стабильна: относительный порядок элементов, которые не должны быть удалены, остается неизменным.
  • Базовая последовательность [ first , last ) не укорачивается операцией удаления. Принимая result за возвращаемый итератор:
  • Каждый элемент диапазона [ result , last ) имеет корректное, но неопределённое состояние, поскольку перемещающее присваивание может исключать элементы, перемещая их из исходного диапазона.
(начиная с C++11)

Параметры

first, last - пара итераторов, определяющих диапазон обрабатываемых элементов
policy - используемая политика выполнения
p - бинарный предикат, который возвращает ​ true если элементы следует считать равными.

Сигнатура функции-предиката должна быть эквивалентна следующей:

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

Хотя сигнатура не обязана иметь const & , функция не должна модифицировать передаваемые ей объекты и должна быть способна принимать все значения типа (возможно const) Type1 и Type2 независимо от категории значения (следовательно, Type1 & не допускается , как и Type1 , если для Type1 перемещение не эквивалентно копированию (since C++11) ).
Типы Type1 и Type2 должны быть такими, чтобы объект типа ForwardIt мог быть разыменован и неявно преобразован к обоим из них. ​

Требования к типам
-
ForwardIt должен удовлетворять требованиям LegacyForwardIterator .
-
Тип разыменованного ForwardIt должен удовлетворять требованиям MoveAssignable .

Возвращаемое значение

Указатель ForwardIt на новый конец диапазона.

Сложность

Дано N как std:: distance ( first, last ) :

1,2) Ровно max(0,N-1) сравнений с использованием operator == .
3,4) Ровно max(0,N-1) применений предиката p .

Исключения

Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, выбрасывает исключение и ExecutionPolicy является одним из стандартных политик , std::terminate вызывается. Для любой другой ExecutionPolicy поведение определяется реализацией.
  • Если алгоритму не удается выделить память, std::bad_alloc выбрасывается.

Возможная реализация

Смотрите также реализации в libstdc++ , libc++ , и 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;
}
**Примечание:** Весь код C++ внутри тегов `
` и `` оставлен без изменений, как и требовалось. HTML-теги и атрибуты также сохранены в оригинальном виде. Переведены только текстовые элементы вне кодовых блоков.

Примечания

Вызов unique обычно сопровождается вызовом функции-члена erase контейнера для фактического удаления элементов из контейнера.

Пример

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    // вектор, содержащий несколько повторяющихся элементов
    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);
    // удалить последовательные (смежные) дубликаты
    auto last = std::unique(v.begin(), v.end());
    // v теперь содержит {1 2 1 3 4 5 4 x x x}, где 'x' неопределено
    v.erase(last, v.end());
    print(2);
    // сортировка с последующим unique, чтобы удалить все дубликаты
    std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
    print(3);
    last = std::unique(v.begin(), v.end());
    // v теперь содержит {1 2 3 4 5 x x}, где 'x' неопределено
    v.erase(last, v.end());
    print(4);
}

Вывод:

@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

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
LWG 202 C++98 поведение было неясным, если элементы
сравниваются с использованием отношения неэквивалентности
поведение является
неопределённым в этом случае

Смотрите также

находит первые два соседних элемента, которые равны (или удовлетворяют заданному предикату)
(шаблон функции)
создаёт копию диапазона элементов, не содержащую последовательных дубликатов
(шаблон функции)
удаляет элементы, удовлетворяющие определённым критериям
(шаблон функции)
удаляет последовательные дублирующиеся элементы
(публичная функция-член std::list<T,Allocator> )
удаляет последовательные дублирующиеся элементы
(публичная функция-член std::forward_list<T,Allocator> )
удаляет последовательные дублирующиеся элементы в диапазоне
(объект функции алгоритма)