C++ <vector> функция erase
eraseиспользуется в vector дляудаления элемента в указанной позицииявляется наиболее гибким методом удаления в контейнерах.
eraseявляется функцией-членом классов контейнеров, используемой дляудаления одного или нескольких элементов в указанных позициях контейнера.. Она принимает параметр-итератор.
eraseОбеспечивает возможность удаления элементов в любой позиции, хотя в vector это менее эффективно, чемpop_back(требует перемещения последующих элементов), но он более мощный.
Определения слов: eraseОзначает «erase», то есть удалить элемент в указанной позиции.
Базовый синтаксис и параметры
eraseЭто функция-член классов контейнеров, требующая итератор, указывающий позицию для удаления.
Формат синтаксиса
// 删除 pos 位置的元素 iterator erase(iterator pos); // 删除 [first, last) 范围内的所有元素 iterator erase(iterator first, iterator last);
Описание параметра
- Параметр:
pos- Тип: iterator (
iterator) - Описание: позиция удаляемого элемента.
- Тип: iterator (
- Параметр:
first,last- Тип: iterator (
iterator) - Описание: итераторы начала и конца диапазона удаляемых элементов. Диапазон удаления — [
first,last), то есть включаетfirstне включаетlast。
- Тип: iterator (
- Возвращаемое значение: Возвращает итератор, указывающий на позицию после последнего удалённого элемента (т.е. на исходный
lastэлемент, находившийся в этой позиции). - Действие: Удаляет элемент в указанной позиции, а последующие элементы сдвигаются вперёд по одному.
- Примечание:
eraseПосле удаления элементов последующие элементы сдвигаются вперёд, и итераторы могут стать недействительными.
Описание функции
Пример
Давайте тщательно освоим это с помощью серии примеров.eraseИспользование.
Пример 1: Базовое использование — удаление одного элемента
Пример
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::cout << "Исходный вектор: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
// Удалить элемент во второй позиции (индекс 1)
auto it = numbers.begin() + 1;
numbers.erase(it);
std::cout << "После удаления: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
Ожидаемый результат выполнения:
原始 vector: 1 2 3 4 5 After deletion: 1 3 4 5
Анализ кода:
numbers.begin() + 1Указывает на второй элемент (со значением 2).eraseУдаляет элемент в этой позиции.- Последующие элементы (3, 4, 5) все сдвигаются на одну позицию вперёд.
Пример 2: Удаление первого и последнего элементов
Использованиеbegin()иend()Можно удалить первый и последний элементы.
Пример
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "Исходный: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
// Удалить первый элемент
numbers.erase(numbers.begin());
std::cout << "После удаления первого элемента: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
// Удалить последний элемент (end() указывает на позицию после последнего элемента)
numbers.erase(numbers.end() - 1);
std::cout << "После удаления последнего элемента: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
Ожидаемый результат выполнения:
原始: 10 20 30 40 50 删除第一个元素后: 20 30 40 50 删除最后一个元素后: 20 30 40
Анализ кода:
erase(begin())Удалить первый элемент.erase(end() - 1)Удалить последний элемент (примечаниеend()указывает на позицию после последнего элемента).
Пример 3: Удаление нескольких элементов (диапазон)
Все элементы в указанном диапазоне можно удалить.
Пример
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << "Исходный: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
// Удалить со второго по пятый элементы (индексы с 1 по 4)
auto first = numbers.begin() + 1;
auto last = numbers.begin() + 5;
numbers.erase(first, last);
std::cout << "После удаления позиций [1, 5): ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
Ожидаемый результат выполнения:
原始: 1 2 3 4 5 6 7 8 9 10 删除位置 [1, 5) 后: 1 6 7 8 9 10
Анализ кода:
erase(first, last)Удалить изfirstвlastвсе элементы до.- Здесь элементы с индексами 1, 2, 3, 4 (2, 3, 4, 5) удаляются.
Пример 4: Удаление всех нечётных чисел
В сочетании с циклом можно удалять элементы, удовлетворяющие условию.
Пример
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << "Исходный: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
// Удалить все нечётные числа
for(auto it = numbers.begin(); it != numbers.end(); ) {
if(*it % 2 == 1) { // Если оно нечётное
it = numbers.erase(it); // erase возвращает итератор на следующий элемент
} else {
++it;
}
}
std::cout << "После удаления нечётных чисел: ";
for(int n : numbers) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
Ожидаемый результат выполнения:
原始: 1 2 3 4 5 6 7 8 9 10 删除奇数后: 2 4 6 8 10
Анализ кода:
- При удалении элементов в цикле будьте осторожны и обновляйте итератор.
eraseВозвращает итератор, указывающий на следующий элемент; это правильный способ удаления.
Пример 5: проблема эффективности erase
При использовании в vectoreraseУдаление элементов в середине менее эффективно.
Пример
#include <vector>
#include <chrono>
int main() {
const int N = 10000;
// Удаление первого элемента (неэффективно)
std::vector<int> v1;
for(int i = 0; i < N; ++i) v1.push_back(i);
auto start1 = std::chrono::high_resolution_clock::now();
while(!v1.empty()) {
v1.erase(v1.begin());
}
auto end1 = std::chrono::high_resolution_clock::now();
auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1);
// Удалить последний элемент (эффективно)
std::vector<int> v2;
for(int i = 0; i < N; ++i) v2.push_back(i);
auto start2 = std::chrono::high_resolution_clock::now();
while(!v2.empty()) {
v2.pop_back();
}
auto end2 = std::chrono::high_resolution_clock::now();
auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2);
std::cout << "Удаление из начала " << N << элементов заняло: << duration1.count() << " microseconds" << std::endl;
std::cout << "Удаление с конца " << N << элементов заняло: << duration2.count() << " microseconds" << std::endl;
return 0;
}
Анализ кода:
- Удаление элемента из начала вектора требует перемещения всех последующих элементов, что очень неэффективно.
- Удаление элементов с конца (
pop_back) не требует перемещения элементов и эффективно. - Если требуется часто удалять элементы из начала, рассмотрите использование
dequeилиlist。
Пример 6: Использование erase для реализации фильтрации данных
eraseМожно использовать для фильтрации данных.
Пример
#include <vector>
#include <string>
// Простая фильтрация неудовлетворительных оценок
void filterFailing(std::vector<int>& scores) {
for(auto it = scores.begin(); it != scores.end(); ) {
if(*it < 60) {
it = scores.erase(it);
} else {
++it;
}
}
}
int main() {
std::vector<int> scores = {85, 92, 45, 78, 55, 90, 67};
std::cout << Исходный балл:;
for(int s : scores) std::cout << s << " ";
std::cout << std::endl;
filterFailing(scores);
std::cout << Проходной балл:;
for(int s : scores) std::cout << s << " ";
std::cout << std::endl;
return 0;
}
Ожидаемый результат выполнения:
原始成绩: 85 92 45 78 55 90 67 及格成绩: 85 92 78 90 67
Анализ кода:
- Использование
eraseМожно реализовать условную фильтрацию. - Удалить scores, которые не проходят (меньше 60).
Другие расширения