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