C++ vector 删除元素

在 C++ 中,当 vector 容器里的某些数据不再需要时,我们可以随时将它们从容器中移除。根据删除需求的不同,常用的有以下 4 种方式:

  • pop_back():删除容器末尾的最后一个元素,执行速度最快。
  • erase():按指定位置删除单个元素,或删除一段连续区间的元素。
  • std::erase():C++20 新增,直接按元素的值删除所有匹配项。
  • clear():一次性清空容器中的所有元素。

删除末尾元素:pop_back()

如果我们只想删掉排在最后面的那个元素,直接调用 pop_back() 成员函数就可以了。其中 pop_back 是 “从末尾弹出” 的意思,刚好与上一节学习的 push_back() 相反。由于删除末尾元素不需要搬移前面的数据,它的执行效率是最高的。

语法:

容器名.pop_back();

说明:

pop_back() 的小括号内不需要传入任何参数。每调用一次 pop_back(),函数就会移除容器末尾的最后一个元素,同时元素数量 size() 会自动减 1。

示例 1:删除末尾元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> scores = {75, 88, 96};
    scores.pop_back();    // 删除末尾元素 96

    std::cout << "剩余元素数量:" << scores.size() << '\n';
    std::cout << scores[0] << ' ' << scores[1] << '\n';
    return 0;
}

运行结果如下。

剩余元素数量:2
75 88

分析:

scores.pop_back(); 会把排在最后的 96 移除,容器中只剩下 75 和 88,因此 scores.size() 变成了 2。下面这段代码中,连续执行增删操作后,nums.back() 最终的值是 20,小伙伴们可以思考一下为什么。

std::vector<int> nums = {10, 20, 30};
nums.pop_back();
nums.push_back(40);
nums.pop_back();

需要注意的是,pop_back() 的返回值类型是 void。它只负责移除末尾元素,并不会把删掉的值返回出来。如果我们既想拿到最后一个元素的值,又想把它删掉,应该先调用 back() 读取,再调用 pop_back() 移除。

std::vector<int> scores = {75, 88, 96};

// 正确方式
int last = scores.back();
scores.pop_back();

// 错误方式
int last = scores.pop_back();

此外,调用 pop_back() 前要确保容器不为空。如果对空容器调用 pop_back() 会引发越界错误,不确定时我们可以先通过 !scores.empty() 做一次判断。

按位置删除元素:erase()

如果要删除的不是最后一个元素,而是开头或中间某个位置的元素,我们就需要使用 erase() 成员函数。

与 insert() 一样,erase() 的参数也不能直接写整数下标,而是通过 容器名.begin() + 下标 来指定位置。它主要有两种常用写法:一种是 “删除单个元素”,另一种是 “删除一段区间的元素”。

1. 删除单个元素

只传入一个位置参数时,erase() 会把该位置上的元素删掉。

语法:

容器名.erase(容器名.begin() + 下标);

说明:

删除指定位置的元素后,排在它后面的所有元素都会自动往前移动一位来补齐空缺,同时容器的 size() 减 1。如果要删除第 1 个元素(下标 0),直接写成 容器名.erase(容器名.begin()) 即可。

示例 2:删除单个元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {10, 20, 30, 40};
    nums.erase(nums.begin() + 1);    // 删除下标 1 处的 20

    std::cout << "剩余元素数量:" << nums.size() << '\n';
    for (int num : nums) {
        std::cout << num << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

剩余元素数量:3
10 30 40

分析:

在这个例子中,nums.erase(nums.begin() + 1); 表示删除下标为 1 的元素 20。把 20 删掉后,后面的 30 和 40 会自动往前顺移一位,随后我们配合范围 for 循环把剩余的 3 个元素打印出来。

这里小伙伴们要留意一个细节:元素往前顺移之后,它们的下标也会跟着变小。比如上面删掉下标 1 的 20 之后,原本排在下标 2 的 30,新的下标就变成了 1。如果需要连续按位置删除多个元素,一定要按删除后的新下标来计算位置。

另外顺便提一点:vector 并没有提供名为 pop_front() 的成员函数,平时想要删除开头的第 1 个元素,使用的就是 nums.erase(nums.begin())。

2. 删除一段区间的元素

除了删除单个元素,erase() 还支持传入起始位置和结束位置,一次性删掉连续的多个元素。

语法:

容器名.erase(容器名.begin() + m, 容器名.begin() + n);

说明:

其中,m 是起始下标,n 是结束下标。这里的区间遵循 “包头不包尾(左闭右开)” 的规则:包含起始下标 m 的元素,但不包含结束下标 n 本身。

比如传入 begin() + 1 和 begin() + 4,实际删掉的是下标 1、2、3 这 3 个位置的元素,下标 4 的元素会保留下来。如果希望从下标 m 开始一直删到容器末尾,第 2 个参数可以直接写成 容器名.end()。

示例 3:删除指定区间的元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {10, 20, 30, 40, 50};

    // 删除下标 1 到 3 的元素
    nums.erase(nums.begin() + 1, nums.begin() + 4);

    std::cout << "剩余元素数量:" << nums.size() << '\n';
    std::cout << nums[0] << ' ' << nums[1] << '\n';
    return 0;
}

运行结果如下。

剩余元素数量:2
10 50

分析:

按照 “包含起点 1、不包含终点 4” 的规则,上面代码实际删掉了下标 1、2、3 处的 20、30、40,而下标 4 处的 50 会保留下来并往前补齐到下标 1 的位置。

平时我们也可以通过简单的减法来快速核对删除个数:终点下标 4 减去起点下标 1 等于 3,说明一共删掉了 3 个元素。

按值删除元素:std::erase()

前面介绍的 容器名.erase() 是根据 “位置” 来删除元素的。但在实际开发中,我们有时并不清楚目标元素排在第几个位置,只想把容器中所有等于某个值的元素全部删掉。

从 C++20 标准开始,<vector> 头文件提供了一个通用函数 std::erase(),可以直接按元素的值删除数据。

语法:

std::erase(容器名, 目标值);

说明:

这里要注意调用写法上的区别:按位置删除写的是成员函数 容器名.erase(...),而按值删除写的是带 std:: 前缀的独立函数 std::erase(容器名, 目标值)。

std::erase() 会从头到尾扫描整个容器,把所有等于 “目标值” 的元素全部移除,并返回本次删除的元素个数。如果容器中不存在该目标值,函数不会报错,而是直接返回 0。

示例 4:按值删除所有匹配元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {10, 20, 30, 20, 40};
    auto count = std::erase(nums, 20);    // 删除所有的 20

    std::cout << "删除个数:" << count << '\n';
    for (int num : nums) {
        std::cout << num << ' ';
    }
    std::cout << '\n';
    return 0;
}

运行结果如下。

删除个数:2
10 30 40

分析:

在这个例子中,我们调用 std::erase(nums, 20) 把 nums 里的两个 20 全部移除,剩下的 10、30、40 会自动往前靠拢对齐。同时,我们配合 auto 关键字定义变量 count 接收返回值,得到本次删除的元素个数为 2。

如果平时不需要统计删除了多少个元素,我们也可以不接收返回值,直接写一句 std::erase(nums, 20); 即可。

清空所有元素:clear()

如果我们需要一次性把 vector 里的所有元素全部删光,让它重新变回空容器,可以使用 clear() 成员函数。

语法:

容器名.clear();

说明:

调用 clear() 会一次性移除容器中的所有元素。执行后,size() 会变成 0,empty() 也会返回 true。

示例 5:清空所有元素

#include <iostream>
#include <vector>

int main() {
    std::vector<int> nums = {10, 20, 30};
    std::cout << "清空前数量:" << nums.size() << '\n';

    nums.clear();    // 清空所有元素
    std::cout << "清空后数量:" << nums.size() << '\n';
    return 0;
}

运行结果如下。

清空前数量:3
清空后数量:0

分析:

nums.clear(); 把容器里的 3 个元素一次性全部清空,因此 nums.size() 的结果从 3 变成了 0。清空之后的 nums 依然可以继续正常使用,我们随时能够调用 push_back() 重新往里面添加新元素。

提示 调用 clear() 只会把实际元素数量 size() 清零,通常不会立即释放 vector 在底层已经申请好的内存容量。关于元素数量与底层容量的关系,后面在 “C++ vector size 与 capacity” 一节中还会详细介绍。

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号