Текущий раздел посвящен вопросу удаления элементов из середины объекта вектора. Если элемент исчезает из вектора и при этом он находился
Как это делается
В этом примере мы наполним объект класса std::vector
целыми числами, а затем выбросим из него конкретные элементы. При этом мы воспользуемся
1. Конечно, прежде чем начинать что-то делать, включим некоторые заголовочные файлы:
#include
#include
#include
2. Далее мы объявляем, что будем использовать пространство имен std
, чтобы поменьше печатать:
using namespace std;
3. Теперь создадим вектор, состоящий из целых чисел, и заполним его некими числами:
int main()
{
vector
4. Удалим некоторые элементы. Что именно? В нашем примере много значений 2
, удалим их:
const auto new_end (remove(begin(v), end(v), 2));
5. Что интересно, это был лишь первый шаг. Вектор все еще имеет прежний размер. Мы укоротим его по-настоящему, написав такую строку:
v. erase(new_end, end(v));
6. Остановимся и выведем на экран содержимое вектора, а затем продолжим:
for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
7. Теперь удалим целый true
, если переданное число
const auto odd ([](int i) { return i % 2 != 0; });
8. Используем функцию remove_if
, передавая ей значения с помощью функции-предиката. Вместо удаления элементов за два шага теперь делаем это за один:
v. erase(remove_if(begin(v), end(v), odd), end(v));
9. Мы удалили все нечетные элементы, но
v.shrink_to_fit();
10. Теперь выведем на экран содержимое вектора после второго раунда удаления элементов и закончим с примером:
for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
}
11. Скомпилировав и запустив программу, вы увидите следующие строки, показывающие результат выполнения операций по удалению элементов:
$ ./main
1, 3, 5, 6, 4, 8,
6, 4, 8,
Как это работает
Из данного примера стало очевидно: при удалении элементов из середины вектора их нужно сначала
Код, удаляющий все значения 2
из вектора, выглядел так:
const auto new_end (remove(begin(v), end(v), 2));
v.erase(new_end, end(v));
Функции std::begin
и std::end
принимают в качестве параметра экземпляр вектора и соответственно возвращают итераторы, которые указывают на
После того как мы передадим их и значение 2
функции std::remove
, она переместит все значения, кроме 2
, вперед точно так же, как если бы мы сделали это вручную с помощью цикла. С первого взгляда рисунок может показаться непонятным. На шаге 2 все еще можно найти значение 2
, а сам вектор должен был стать короче, поскольку содержал четыре таких значения. Вместо этого значения 4
и 8
, присутствовавшие в оригинальном массиве, встречаются дважды. Что происходит?