前言
动态数组时一个线性容器,增删改查是容器必备的功能;
动态数组(vector)类模板提供了一个成员函数erase(),用于删除数组中的元素。erase有多个重载形式。本文介绍使用迭代器进行元素的删除。
移除单个元素
iterator erase( iterator position );
pos
:指向要移除元素的迭代器。- 返回值:一个指向被移除元素之后元素的迭代器。如果
pos
是容器的最后一个迭代器,则返回end()
。
删除一段连续的元素
iterator erase( iterator first, iterator last );
first
:指向要移除的第一个元素的迭代器。last
:指向要移除的范围之外第一个元素的迭代器(即范围结束的后一个位置)。- 返回值:一个指向
last
所指位置(即原始范围之后)的迭代器。
迭代器失效
erase操作可能会使迭代器失效。
迭代器在vector中类似于链表中节点内指向下一节点地址的指针,在使用erase删除元素后,被删除元素的迭代器指向的下一个元素的地址将被置空。
所以如果在循环遍历vector时,如果使用erase删除元素,可能会出现程序崩溃。
代码示例
std::vector<int> vec = {1,2,3,4,5,6,7,8,9}
// 例子一
for(auto& item : vec)
{
if(item == 2)
{
vec.erase(item);
}
}
// 例子二
for(auto it = vec.begin(); it != vec.end(); it++)
{
if(item == 2)
{
vec.erase(item);
}
}
以上两种方式都会出现迭代器失效,程序运行崩溃的问题。
分析
以上两种方式都会出现迭代器失效,程序运行崩溃的问题。
具体原因是我们在for循环时,会自动将迭代器指针指向下一个元素。这个过程不由我们控制,所以在使用erase删除元素后,迭代器失效,无法获取下一个元素,迭代器指针指向的地址也是无效的。
处理方式
将迭代器指针的变化由我们来控制,不由for控制。
借助erase的返回值(一个指向被移除元素之后元素的迭代器)来手动管理迭代器指针的改变。
正确方式
std::vector<int> vec = {1,2,3,4,5,6,7,8,9}
// 例子一
for(auto it = vec.begin(); it != vec.end();)
{
if(item == 2)
{
it = vec.erase(item);
}
else
{
it++;
}
}
erase 在删除元素时会返回被删元素的下一个元素的迭代器