Добрый день, всем привет!
Снова в эфире рубрика «Вы не спрашивали, но мы отвечаем», раздел «Программирование», глава «Что нового я узнал в сейчас лет».
Например, не так давно я узнал, что <a href="https://en.cppreference.com/w/cpp/container/unordered_map">std::unordered_map</a>
не сортирует данные в отличие от <a href="https://en.cppreference.com/w/cpp/container/map">std::map</a>
. А много-много лет назад (в 2007-м году) нам пришлось реализовывать бинарный поиск, чтобы ускорить вставку элементов в std::map
(там жил кэш текстур) вместо того, чтобы взять std::unordered_map
. Наш просчёт немного оправдывает то, что мы были молоды, неопытны и std::unordered_map
появился спустя пять с лишним лет после описываемых событий.
Вообще, я не отношусь к тем людям, которые ежедневно читают свежайший стандарт C++, подчеркивая карандашиком важные места. Скорее, я начинаю читать стандарт, когда нужно найти решение текущей задачи. Так, например, я совершенно случайно наткнулся на <a href="https://en.cppreference.com/w/cpp/memory/enable_shared_from_this">std::enable_shared_from_this</a>
, когда просматривал код нашего проекта, поминая тимлида нехорошими словами . Там был метод типа make() у класса, который должен вернуть <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr">std::shared_ptr</a>
от экземпляра этого класса. Если вы наследуете класс от std::enable_shared_from_this
, то у вас появляется метод <a href="https://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this">shared_from_this()</a>
, и дело в шляпе. Поскольку это было пять лет назад, уже не помню всех подробностей, но сначала было не очень, а потом резко стало хорошо! )
Каких-то одиннадцать лет назад я написал статью про эффективное удаление элементов массива. Тогда единственный способ, который я знал, выглядел следующим образом:
auto iter=data.begin()
while(iter != data.end()) {
if (condition(*iter)) {
iter = puf(data, iter);
else {
++iter;
}
}
Вся упомянутая в статье магия с перемещением в конец массива и удалением происходит в puf()
. ЗдОрово, правда?
Оказывается, есть метод лучше, и имя ему — <a href="https://en.cppreference.com/w/cpp/algorithm/remove">std::remove_if()</a>
, а самый интересный момент, что этот метод не удаляет элементы, а перемещает их в конец массива, возвращая итератор на начало этого кладбища погибших элементов. Между прочим, эксперимент показал, что после итератора лежит мусор.
С новыми знаниями, удаление элементов из контейнера будет выглядеть так:
auto iter = std::remove_if(data.begin(), data.end(), condition);
data.erase(iter, iter.end());
Что является более продвинутым вариантом и пишется короче, с чем я вас и поздравляю!
Фунция std::remove_if()
удаляет элементы, для которых условие истинно, а std::remove()
удаляет элементы с конкретным значением.