удаление элементов по значению в C ++ - действительно ли предпочтительная идиома состоит из двойного отрицания? - PullRequest
1 голос
/ 05 сентября 2011

Я наткнулся на этот ответ на вопрос об удалении элементов по значению в C ++:

C ++ Стереть векторный элемент по значению, а не по позиции?

В основном:

vec.erase(std::remove(vec.begin(), vec.end(), valueToRemove), vec.end());

Ответ имеет смысл, но разве это не плохой стиль?Логика состоит из двойного негатива ... есть ли более чистый способ сделать это?

Ответы [ 3 ]

6 голосов
/ 05 сентября 2011

Удаление элемента из коллекции состоит из двух шагов:

  • Перемещение всех последующих элементов для заполнения отверстий, созданных совпадениями
  • Маркировка нового конца

В стандартной библиотеке C ++ это две отдельные функции, remove и erase соответственно.

Можно, конечно, представить себе функцию типа erase_if, которую было бы проще использовать, но, видимо, текущий код считается достаточно хорошим.Конечно, вы можете написать свой собственный remove_if.

4 голосов
/ 05 сентября 2011

Это неплохой и эффективный способ удаления элементов из вектора на основе условия в линейное время . Смотрите это видео с 35-й минуты. STL объяснение идиомы стирания и удаления

1 голос
/ 05 сентября 2011

Помните, что существуют различные типы контейнеров: смежные против узловых и последовательные против ассоциативных.

Контейнеры на основе узлов позволяют эффективно стирать / вставлять.Последовательные контейнеры упорядочивают элементы по порядку вставки (то есть по положению), а ассоциативные контейнеры упорядочивают их по значению (ключу).

Все текущие ассоциативные контейнеры (map / set / unordered) основаны на узлах, и с ними вы можетестереть элементы напрямую, и вы должны напрямую использовать элемент-элемент erase.Списки являются контейнерами последовательностей на основе узлов, поэтому вы можете эффективно удалять отдельные элементы, но поиск элемента по значению занимает линейное время, поэтому списки предлагают функцию члена remove.Только контейнеры последовательности (vector и deque) не имеют простого способа стереть элементы по значению, и вот тут появляется бесплатный алгоритм remove, который сначала переставляет последовательность, чтобы затем разрешить члену контейнера eraseдля эффективного удаления в конце контейнера.

В отличие от многих общих аспектов стандартной библиотеки, которые работают без знания базового контейнера, идиома копирования / стирания является одной из тех вещей, которые требуютнемного подробных знаний о различиях между контейнерами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...