您的位置:首页 > 编程语言 > C语言/C++

C++复习之迭代器失效的问题

2020-07-14 05:22 375 查看

迭代器的失效问题

第一种场景:

首先咱们先用库里面自带的vector容器,把容器中所有偶数删除

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
for (int i = 0; i < 20; ++it)
{
vec.push_back(rand() % 100 + 1);
}
//把容器中所有偶数删除
auto it = vec.begin();
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
//迭代器失效的问题第一次调用erase之后,迭代器it就失效了
vec.erase(it);//erase是vector底层提供的删除方法,把it指向的当前元素删除掉
}
}
return 0;
}

当我们执行程序之后,会发现进程意外中止。这是因为第一次调用erase之后,迭代器it就失效了 ,之后的for循环内的 ++it 操作就是出错。
如果只删除一次,则进程正常结束。

for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
vec.erase(it);
break;
}
}

原因是当你删除一个元素后,从这个元素的位置到容器结尾之间的迭代器全部失效。再进行++、–、!=等操作时,都会出现错误。

第二种场景

给容器内所有的偶数前面添加一个小于偶数值1的数字

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
for (int i = 0; i < 20; i++)
{
vec.push_back(rand() % 100 + 1);
}
//给容器内所有的偶数前面添加一个小于偶数值1的数字
auto it = vec.begin();
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
//这里的迭代器在一次insert后,iterator就失效了
vec.insert(it,*it - 1);
}
}
return 0;
}

当我们执行程序之后,会发现进程意外中止。这是因为第一次调用erase之后,迭代器it就失效了 ,之后的for循环内的 ++it 操作就是出错。
如果只插入一次,则进程正常结束。
即加入break。

auto it = vec.begin();
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
vec.insert(it,*it - 1);
break;
}
}

增加也是一样,原因是当你插入一个元素后,如果容器不出现扩容的情况,从这个元素的插入位置到容器结尾之间的迭代器全部失效。再进行++、–、!=等操作时,都会出现错误。如果容器出现扩容的情况,系统会开辟一个新的内存,在原来内存上保存的所有迭代器都会失效。

迭代器为什么会失效?
1.当容器调用erase方法后,当前位置到容器末尾元素的所有迭代器全部都失效了。
2.当容器调用insert方法后, 当前位置到容器末尾元素的所有迭代器全部都失效了。insert如果引起容器内存扩容,原来容器的所有的迭代器完全失效。

迭代器失效后的解决方法

对插入/删除点的迭代器进行更新操作
以删除为例:当你将当前位置的元素删除后,指向当前位置的迭代器就失效了,会在当前位置产生一个新的迭代器iterator并返回。所以我们通过更新迭代器的方法来解决这个问题。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
for (int i = 0; i < 20; i++)
{
vec.push_back(rand() % 100 + 1);
}
//第一次打印
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
//第一种场景删除
//把容器中所有偶数删除
auto it = vec.begin();
while(it != vec.end())
{
if (*it % 2 == 0)
{
//迭代器失效的问题第一次调用erase之后,迭代器it就失效了
it = vec.erase(it);//更新当前的迭代器
}
else
{
++it;
}
}
#endif
//再次打印
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
return 0;
}

以插入为例:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
for (int i = 0; i < 20; i++)
{
vec.push_back(rand() % 100 + 1);
}
//第一次打印
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
//第二中场景插入
//给容器内所有的偶数前面添加一个小于偶数值1的数字
auto it = vec.begin();
for (; it != vec.end(); ++it)
{
if (*it % 2 == 0)
{
it = vec.insert(it,*it - 1);
++it;//当如果当前是偶数执行插入操作后,会把原来位置上的元素挤到下一个位置,所以迭代器需要++两次
}
}
//再次打印
for (int v : vec)
{
cout << v << " ";
}
cout << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: