std::unique
| Определено в заголовке <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) и возвращает итератор, указывающий на новый конец диапазона.
operator==.operator== не задает отношение эквивалентности, поведение не определено.p.p не задает отношение эквивалентности, поведение не определено.policy.true:
|
|
(до C++20) |
|
|
(начиная с 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)
|
| Требования к типам | ||
-
ForwardIt
должен удовлетворять требованиям
LegacyForwardIterator
.
|
||
-
ForwardIt
должен удовлетворять требованиям
MoveAssignable
.
|
||
Возвращаемое значение
Указатель
ForwardIt
на новый конец диапазона.
Сложность
Дано N как std:: distance ( first, last ) :
Исключения
Перегрузки с параметром шаблона с именем
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; } |
` и `` оставлен без изменений, как и требовалось. 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 |
поведение было неясным, если элементы
сравниваются с использованием отношения неэквивалентности |
поведение является
неопределённым в этом случае |
См. также
| находит первые два соседних элемента, которые равны (или удовлетворяют заданному предикату) (шаблон функции & объект функции алгоритма) | |
(C++20) |
|
| создаёт копию диапазона элементов, не содержащего последовательных дубликатов (шаблон функции & объект функции алгоритма) | |
(C++20) |
|
| удаляет элементы, удовлетворяющие заданным критериям (шаблон функции & объект функции алгоритма) | |
(C++20)(C++20) |
|
| удаляет последовательные дублирующиеся элементы (открытая функция-член std::list<T,Allocator>)
| |
| удаляет последовательные дублирующиеся элементы (открытая функция-член std::forward_list<T,Allocator>)
| |
(C++20) |
удаляет последовательные дублирующиеся элементы в диапазоне (объект функции алгоритма) |