C++ <vector> функция erase

класс контейнера C++ <vector>


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)
    • Описание: позиция удаляемого элемента.
    • Параметр: first, last
      • Тип: iterator (iterator)
      • Описание: итераторы начала и конца диапазона удаляемых элементов. Диапазон удаления — [first, last), то есть включаетfirstне включаетlast。

    Описание функции

    • Возвращаемое значение: Возвращает итератор, указывающий на позицию после последнего удалённого элемента (т.е. на исходныйlastэлемент, находившийся в этой позиции).
    • Действие: Удаляет элемент в указанной позиции, а последующие элементы сдвигаются вперёд по одному.
    • Примечание: eraseПосле удаления элементов последующие элементы сдвигаются вперёд, и итераторы могут стать недействительными.

    Пример

    Давайте тщательно освоим это с помощью серии примеров.eraseИспользование.

    Пример 1: Базовое использование — удаление одного элемента

    Пример

    #include <iostream>
    #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
    

    Анализ кода:

    1. numbers.begin() + 1Указывает на второй элемент (со значением 2).
    2. eraseУдаляет элемент в этой позиции.
    3. Последующие элементы (3, 4, 5) все сдвигаются на одну позицию вперёд.

    Пример 2: Удаление первого и последнего элементов

    Использованиеbegin()иend()Можно удалить первый и последний элементы.

    Пример

    #include <iostream>
    #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 <iostream>
    #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 <iostream>
    #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 <iostream>
    #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 <iostream>
    #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).

    класс контейнера C++ <vector>

    Другие расширения