std::cout << '\n';
}
5. Нам осталось реализовать только две функции quick_remove_at
Обе функции принимают ссылку на вектор, содержащий значения
int
), так что мы не решаем за пользователя, какой тип вектора он задействует. Для нас это будет вектор, содержащий значения типа T
. Первая функция quick_remove_at
принимает значения template
void quick_remove_at(std::vector
{
6. Сейчас перейдем к самому главному — быстрому удалению элементов. При этом нужно постараться не перемещать слишком большого количества оставшихся элементов. Во-первых, просто возьмем значение последнего элемента вектора и запишем его на место элемента, который должен быть удален. Во-вторых, отбросим последний элемент. Вот и все, только два шага. Мы добавим в этот код небольшую проверку безопасности. Если значение индекса очевидным образом выходит за пределы вектора, мы не станем ничего делать. В противном случае код будет давать сбой для пустого вектора.
if (idx < v.size()) {
v[idx] = std::move(v.back());
v.pop_back();
}
}
7. Другая реализация метода quick_remove_at
std::vector
. Получить такой обобщенный тип несложно, поскольку для контейнеров STL уже определены подобные типы.template
void quick_remove_at(std::vector
typename std::vector
{
8. Теперь получим доступ к значению, на которое указывает итератор. Как и в другой функции, перепишем его с помощью последнего элемента вектора. Поскольку мы работаем не с числовым индексом, а с итератором, следует выполнять более аккуратную проверку на безопасность. Если итератор указывает на специальную конечную позицию, то разыменовывать его нельзя.
if (it != std::end(v)) {
9. Внутри этого блока if
*it = std::move(v.back());
v.pop_back();
}
}
10. Вот и все. Компиляция и запуск программы дадут следующий результат:
$ ./main
123, 456, 200, 100,
100, 456, 200,
Как это работает
Функция quick_remove_at
Оба шага в коде примера выглядят следующим образом:
v.at(idx) = std::move(v.back());
v.pop_back();
В версии с итераторами шаги выглядят примерно так же:
*it = std::move(v.back());
v.pop_back();
По логике, мы