Правило Erase — Remove — загальновживаний в мові програмування C++ метод видалення з контейнера STL елементів, які задовольняють певним критеріям.

Мотивація ред.

Досить часто постає потреба видалити з контейнера всі елементи, які мають певне значення або відповідають певному критерію. У мові C++ це можна реалізувати різними методами, зокрема за допомогою самостійно організованого поелементного обходу контейнера. Однак бажано використовувати алгоритми зі стандартної бібліотеки для таких завдань[1].

Бібліотека algorithm пропонує алгоритми remove або remove_if для цього. Але оскільки ці алгоритми працюють із низкою елементів, обмежених двома заданими ітераторами, вони не можуть знати нічого про внутрішню організацію самого контейнера[2]. Таким чином, ніякі елементи фактично не будуть видалені з контейнера за допомогою лише цих функцій. Після використання однієї з цих функцій всі елементи, що не відповідають критеріям видалення, просто будуть перенесені в передню частину діапазону зі збереженням відносного порядку. Коли це буде зроблено, функція remove або remove_if поверне ітератор, який вказує на елемент наступний за останнім не переміщеним елементом.

Щоб насправді видалити непотрібні елементи з контейнера, використовують поєднання функції remove із викликом функції erase, яка безпосередньо й виконує видалення елементів із контейнера, використовуючи ітератор, який повернула попередньо викликана функція remove. Звідси походить і сама назва методу «Erase — Remove».

Приклад ред.

#include <vector>
#include <iostream>
#include <algorithm>
 
bool is_odd(int i)
{
  return (i % 2) != 0;  
}

void print_item(int i)
{
  std::cout << i << ' ';
}

void print(const std::vector<int> &vec)
{
  for_each(vec.begin(), vec.end(), print_item);
  std::cout << std::endl;
}
 
int main()
{
  // ініціалізуємо вектор числами 0-9.
  std::vector<int> v(10);
  for (unsigned i = 0; i < v.size(); ++i)
    v[i] = i;
  print(v);
 
  // видаляємо всі елементи рівні 5
  v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() ); 
  print(v); 
  
  // видаляємо всі непарні елементи
  v.erase( std::remove_if( v.begin(), v.end(), is_odd ), v.end() );
  print(v);

  return 0;  
}

/*
Вивід:
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 6 7 8 9 
0 2 4 6 8 
*/

Посилання ред.

  1. Meyers, Scott (2001). Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley.
  2. Josuttis, Nicolai (1999). C++ Standard Library – A Tutorial and Reference. Addison-Wesley.