Namespaces
Variants

std:: remove, std:: remove_if

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
remove remove_if
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>
(1)
template < class ForwardIt, class T >
ForwardIt remove ( ForwardIt first, ForwardIt last, const T & value ) ;
(constexpr начиная с C++20)
(до C++26)
template < class ForwardIt, class T = typename std:: iterator_traits

< ForwardIt > :: value_type >
constexpr ForwardIt remove ( ForwardIt first, ForwardIt last,

const T & value ) ;
(начиная с C++26)
(2)
template < class ExecutionPolicy, class ForwardIt, class T >

ForwardIt remove ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last, const T & value ) ;
(начиная с C++17)
(до 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 ) ;
(начиная с C++26)
template < class ForwardIt, class UnaryPred >
ForwardIt remove_if ( ForwardIt first, ForwardIt last, UnaryPred p ) ;
(3) (constexpr начиная с C++20)
template < class ExecutionPolicy, class ForwardIt, class UnaryPred >

ForwardIt remove_if ( ExecutionPolicy && policy,

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

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

1) Удаляет все элементы, равные value (используя operator == ).
3) Удаляет все элементы, для которых предикат p возвращает true .
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)


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

(до C++11)

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

(начиная с 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

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

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