【C++】vector,list迭代器失效
创始人
2024-04-02 02:11:03

1.vector迭代器失效

vector容器的物理基础是线性表,底层是指针变量实现的。

在这里导致vector迭代器失效的原因会有两种-----插入失效,删除失效。

1.2插入数值导致迭代器失效

1.21扩容导致迭代器失效

我们在一块vector空间插入pos(20)

 但是这个空间只能存放五个数,要想插入数据,就要重新扩容2倍(一般扩容时,二倍是比较合理的)。

 当释放小空间时,pos迭代器仍然指向他,所以释放后,pos就是野指针了,所以造成pos迭代器失效。

举个例子:我们在所有的偶数前面插入这个偶数的2 倍,由于我们写的迭代器可能存在误差,我们直接调用std库里的迭代器进行测试。

int main()
{std::vector v;  //调用std中的vectorv.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.insert(it, *it * 2);}++it;}for (auto e : v){cout << e << endl;}return 0;
}

1.22pos指向位置改变导致迭代器失效 

对于上面的代码我们直接给他扩容让他空间足够。

int main()
{std::vector v;  //调用std中的vectorv.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.insert(it, *it * 2);}++it;}for (auto e : v){cout << e << endl;}return 0;
}

 编译直接报错,为啥空间足够,迭代器也会失效呢?

按我们所想的代码,打印的是1,4,2,3,8,4,5。。。但是这全部是2,而且还是在同一个地方,不是在偶数前面插入的4。

这个原因是啥?

我们加入数据2的下标是[1],当我们插入4后,我们想让下标进行移动到数据3处,但是这个下标现在在数据4的下标[1]处,然后下标++,到数据2的下标[2]处,诶我们发现,这个下标转转回回又到了数据2处,然后又在他前面插入。所以会一直插入4在2前面。

所以我们可以用一个指针去接收插入后的迭代器。

int main()
{std::vector v;  //调用std中的vectorv.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){it=v.insert(it, *it * 2);it += 2;}else {++it;}}for (auto e : v){cout << e << endl;}return 0;
}

如果按照第一种情况,扩容使迭代器失效,那我们不扩容看看加一个指针接收还会不会失效。

如果我们不用指针接收,单纯让it每次+2行吗?

不扩容的情况不行: 

 而扩用的可以,但是用指针接收也不费事,别用这两种代码。

1. 3删除erase导致迭代器失效

接下来我们删除vector中的偶数,看看能不能正常运行。

int main()
{std::vector v;  //调用std中的vectorv.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.erase(it);}++it;}for (auto e : v){cout << e << endl;}return 0;
}

迭代器又一次失效了。

这个是因为当我们删除2后,pos指针的位置还在原来的位置,但是3却往前挪了,而pos指向3时编译器认为指针不在指向原来的数据发生改变,所以迭代器就会失效。 

 这个解决方法也是指针接收。

 这里的it不用加两回了,因为删除本身就是一个加号。

2.list迭代器失效 

相对于底层是顺序表的vector来说,list的底层是链表,这就使他在插入时不需要大量挪动数据。也就是说list在进行插入插入操作时不会迭代器失灵。 

vector在插入时出现了野指针问题,但是在list中,插入时会创造一个新节点,指针仍旧指向原来那个结点,不会出现野指针。但是删除操作就会导致迭代器失效了。因为结点删除了但是指针还在,指针就是野指针了。 

2.1删除导致迭代器失效: 

但是list容器在删除是也会导致迭代器失效问题,情况如下:

int main()
{std::list lt;  lt.push_back(1);lt.push_back(2);lt.push_back(4);lt.push_back(5);lt.push_back(8);lt.push_back(10);for (auto e : lt){cout << e << " ";}cout << endl;auto pos = find(lt.begin(), lt.end(), 5); //在list范围找5if (pos != lt.end()){lt.erase(pos);pos++;}for (auto e : lt){cout << e << " ";}return 0;}

 就比如我们要删除5,那么这个结点被删除之后而pos指针就变成野指针了。

也就是删除操作时会使迭代器失效。

这里把pos++代码去掉,就可以正常运行了。

总结:迭代器之所以失效最大的原因是成为野指针了。

 总是感觉这篇博客有一点水,但是真没内容写了,就这吧!

相关内容

热门资讯

长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...