Namespaces
Variants

std::remove, std::remove_if

Из ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы для диапазонов (C++20)
Ограниченные алгоритмы, например, ranges::copy, ranges::sort, ...
Неизменяющие операции последовательности    
Пакетные операции
(C++17)
Операции поиска
Изменяющие операции последовательности
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции заполнения
Операции удаления
Операции изменения порядка
(until C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разделения
(C++11)    

Операции сортировки
Операции двоичного поиска
(на разделённых диапазонах)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для пояснения*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Определён в заголовке <algorithm>
template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
(1) (until C++26)
(constexpr since C++20)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last,
                            const T& value );
(since C++26)
template< class ExecutionPolicy, class ForwardIt, class T >
ForwardIt remove( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, const T& value );
(2) (since C++17)
(until C++26)
template< class ExecutionPolicy, class ForwardIt,
          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
ForwardIt remove( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, const T& value );
(since C++26)
template< class ForwardIt, class UnaryPred >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPred p );
(3) (constexpr since C++20)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >
ForwardIt remove_if( ExecutionPolicy&& policy,
                     ForwardIt first, ForwardIt last, UnaryPred p );
(4) (since C++17)

Удаляет все элементы, удовлетворяющие определённым критериям, из диапазона [first, last) и возвращает итератор, указывающий на новый конец диапазона (past-the-end).

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

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

(until C++20)

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

(since C++20)


Если value type типа ForwardIt не является CopyAssignable, поведение не определено.

(until C++11)

Если тип *first не является MoveAssignable, поведение не определено.

(since C++11)

Объяснение

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

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

Параметры

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

Выражение p ( v ) должно быть преобразуемо в bool для каждого аргумента v типа (возможно const) VT , где VT - тип значения ForwardIt , независимо от категории значения , и не должно изменять v . Следовательно, тип параметра VT & не допускается , как и VT , если для VT перемещение не эквивалентно копированию (since C++11) . ​

Требования к типам
-
ForwardIt должен удовлетворять требованиям LegacyForwardIterator .
-
UnaryPredicate должен удовлетворять требованиям Predicate .

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

Итератор за концом нового диапазона значений (если это не end , то он указывает на неопределённое значение, как и итераторы любых значений между этим итератором и end ).

Сложность

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

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

Исключения

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

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

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

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;
}
Все HTML-теги, атрибуты и код внутри `
` тегов сохранены без изменений. Только текстовые элементы вне тегов кода были переведены на русский язык с сохранением профессиональной терминологии C++.

Примечания

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

Того же эффекта можно достичь с помощью следующих нечленных функций:

(since C++20)

Аналогично названные функции-члены контейнеров member functions list::remove , list::remove_if , forward_list::remove и forward_list::remove_if удаляют убранные элементы.

Эти алгоритмы нельзя использовать с ассоциативными контейнерами, такими как std::set и std::map , поскольку их типы итераторов не разыменовываются в MoveAssignable типы (ключи в этих контейнерах не могут быть изменены).

Стандартная библиотека также определяет перегруженную версию std::remove в <cstdio> , которая принимает const char * и используется для удаления файлов.

Поскольку std::remove принимает value по ссылке, это может привести к неожиданному поведению, если передается ссылка на элемент диапазона [ first , last ) .

Макрос тестирования возможностей Значение Стандарт Возможность
__cpp_lib_algorithm_default_value_type 202403 (C++26) List-инициализация для алгоритмов ( 1,2 )

Пример

Следующий код удаляет все пробелы из строки, сдвигая все непробельные символы влево и затем стирая лишнее. Это пример 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';
    // The spaces are removed from the string only logically.
    // Note, we use view, the original string is still not shrunk:
    std::cout << "3) " << std::quoted(std::string_view(str1.begin(), noSpaceEnd))
              << ", size: " << str1.size() << '\n';
    str1.erase(noSpaceEnd, str1.end());
    // The spaces are removed from the string physically.
    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}}));
}

Вывод:

1) "Quick  Red  Dog"
2) "QuickRedDog Dog"
3) "QuickRedDog", size: 15
4) "QuickRedDog", size: 11
5) "JumpedOverALazyFox"

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

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

DR Applied to Behavior as published Correct behavior
LWG 283 C++98 T was required to be EqualityComparable , but
the value type of ForwardIt is not always T
required the value type of ForwardIt
to be CopyAssignable instead

См. также

копирует диапазон элементов, пропуская те, которые удовлетворяют определённым критериям
(шаблон функции & функциональный объект алгоритма)
удаляет последовательные повторяющиеся элементы в диапазоне
(шаблон функции & функциональный объект алгоритма)
удаляет элементы, удовлетворяющие определённым критериям
(функциональный объект алгоритма)