Jump to content

Идиома «Стереть–удалить»

(Перенаправлено с идиомы «Стереть-удалить »)

Идиома стирания-удаления — это распространенный метод C++ для исключения элементов, соответствующих определенному критерию, из контейнера стандартной библиотеки C++ . [1] [2] [3]

Мотивация

[ редактировать ]

Распространенной задачей программирования является удаление из коллекции всех элементов, имеющих определенное значение или удовлетворяющих определенному критерию . В C++ этого можно добиться с помощью написанного вручную цикла. Однако для таких задач предпочтительнее использовать алгоритм из стандартной библиотеки C++. [1] [2] [3]

Функция-член erase может использоваться для удаления элемента из коллекции, но для контейнеров, основанных на массиве, таких как vector, все элементы после удаленного элемента необходимо переместить вперед, чтобы избежать «пробелов» в коллекции. Вызов стирания несколько раз в одном и том же контейнере приводит к большим накладным расходам при перемещении элементов.

The algorithm библиотека предоставляет remove и remove_if алгоритмы для этого. Поскольку эти алгоритмы работают с диапазоном элементов, обозначенным двумя прямыми итераторами, они не знают базового контейнера или коллекции. [1] [4]

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

Поскольку никакие элементы фактически не удаляются и контейнер сохраняет тот же размер, длина хвоста массива равна количеству «удаленных» элементов; эти элементы остаются в памяти, но в неопределенном состоянии. remove возвращает итератор, указывающий на первый из этих хвостовых элементов, чтобы их можно было удалить с помощью одного вызова erase.

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

Начиная с C++20, свободные функции std::erase и std::erase_if предоставляются для контейнеров STL. Эти удобные функции можно использовать для правильного стирания элементов, не требуя от программиста явного использования идиомы стирания-удаления. [5]

Ограничение

[ редактировать ]

Идиому стереть-удалить нельзя использовать для контейнеров, которые возвращают const_iterator (например: набор ) [6]

std::remove и/или std::remove_if не сохранять удаленные элементы (в отличие от std::partition, std::stable_partition). Таким образом, метод стирания-удаления можно использовать только с контейнерами, содержащими элементы с полноценной семантикой, без утечек ресурсов. [7]

Компилятор Explorer

// Use g++ -std=c++11 or clang++ -std=c++11 to compile.

#include <algorithm>  // remove and remove_if
#include <iostream>
#include <vector>

void Print(const std::vector<int>& vec) {
  for (auto val : vec) {
    std::cout << val << ' ';
  }
  std::cout << '\n';
}

int main() {
  std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  Print(v);

  // Removes all elements with the value 5.
  v.erase(std::remove(v.begin(), v.end(), 5), v.end());
  Print(v);

  // Removes all odd numbers.
  v.erase(std::remove_if(v.begin(), v.end(), [](int val) { return val & 1; }),
          v.end());
  Print(v);
}

/*
Output:
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. ^ Перейти обратно: а б с Мейерс, Скотт (2001). Эффективный STL: 50 конкретных способов улучшить использование стандартной библиотеки шаблонов . Аддисон-Уэсли.
  2. ^ Перейти обратно: а б Саттер, Херб ; Александреску, Андрей (2004). Стандарты кодирования на C++: 101 правило, рекомендации и передовой опыт . Аддисон-Уэсли.
  3. ^ Перейти обратно: а б Скотт Мейерс, «Алгоритмы STL против рукописных циклов», доктор Доббс , 25 октября 2001 г. [1]
  4. ^ Джосуттис, Николай (1999). Стандартная библиотека C++ — учебное пособие и справочник . Аддисон-Уэсли.
  5. ^ «std::erase, std::erase_if (std::vector) — cppreference.com» . ru.cppreference.com . Проверено 9 декабря 2021 г.
  6. ^ «Стереть–удалить идиому с помощью std::set» . stackoverflow.com . Переполнение стека. 25 сентября 2010 г. Проверено 14 апреля 2013 г.
  7. ^ Мейерс, Скотт (2001). Эффективный STL: 50 конкретных способов улучшить использование стандартной библиотеки шаблонов . Бостон: Аддисон-Уэсли. стр. 143–145 . ISBN  0201749629 . OCLC   46713127 .
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 9b9964a89ee812f507a47d2f8ebcc53f__1716259800
URL1:https://arc.ask3.ru/arc/aa/9b/3f/9b9964a89ee812f507a47d2f8ebcc53f.html
Заголовок, (Title) документа по адресу, URL1:
Erase–remove idiom - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)