vector

文章讨论了C++标准库中的vector容器在插入和删除操作时迭代器可能失效的问题,以及扩容对迭代器的影响。文中提到了内部和外部迭代器失效的场景,并建议在insert和erase后使用返回的新迭代器。此外,还提到了vector在拷贝和reserve操作中可能出现的浅拷贝问题,可能导致对象被析构两次。解决方案包括使用深拷贝和避免模板匹配错误。
摘要由CSDN通过智能技术生成


在这里插入图片描述

使用这种方式定义vector和我们在顺序表中定义有何区别?

本质上是一样的。只不过这种利用了指针-指针的性质。start是左闭,finish,end of storage是右开的
在这里插入图片描述

vector成员变量的start,finish,end of storage和我们以前顺序表结构体的size,capacity,int* arr相比有什么优点呢?

在这里插入图片描述

我们在string模拟insert时,pos==0时因为无符号 - -仍然是无符号导致循环停不下来。
这里指针start不会是0号地址,0号地址是无效地址,所以while(pos>=start)条件会停下来,这是start.finsih,eof带给我们的优势。

著名问题:迭代器失效

问题引入

情况一,vector无数据,push_back复用insert,代码崩了
在这里插入图片描述
情况二,即使push_back不复用insert,在insert时如果发生扩容,就会产生问题插入一个随机值
在这里插入图片描述

解决内部迭代器失效

在这里插入图片描述
原先的pos指向旧空间,如果发生扩容开辟了新空间,我们就要找到新空间中pos相对的位置,不然就会发生迭代器失效问题,程序会崩溃或者随机值,并且这种情况是偶发性的错误(如果不扩容那没什么问题)
在这里插入图片描述

外部迭代器p失效

在这里插入图片描述

insert以后迭代器可能会失效(失效的原因还是扩容,p不指向原来的空间并且虽然内部迭代器更新了但更新的是形参改变不了实参!),如果不扩容就是正常的。

为了解决形参pos的改变不会修改实参p,我们试图加上&,但是这会导致begin()函数调用和表达式返回临时变量具有常性,造成权限放大,又试图加上const,但这样函数体内pos还要更新,更是不可能加上const
在这里插入图片描述
在这里插入图片描述

所以,insert以后就不要使用这个迭代器p了,因为它可能失效了
在这里插入图片描述

那怎么办呢?
库里面Insert带了一个返回值,返回新插入元素的位置的迭代器!
如果你想继续访问P那么就去接收返回值。
在这里插入图片描述

在这里插入图片描述

erase后迭代器失效

在这里插入图片描述
本来1 2 3 4 5
现在要删头,删除后我还要访问it和++it,此时原来指向1的it,现在指向2,就是说it不指向原来的元素了,此时认定erase后迭代器也会失效
上面是我们模拟实现的,在stl标准库中,对这种erase后继续访问it迭代器的行为直接进行了崩溃处理
在这里插入图片描述
linux中头删或者尾删貌似没什么问题
在这里插入图片描述

但是有些情况下linux的这种不直接报错,反而更加恶心
删除所有的偶数
在这里插入图片描述
情景1
1 2 3 4 5
删除后1 3 5
it指向2,删除2,迭代器失效指向3,后++it指向了4,再删除4,迭代器失效指向5,后++it循环结束
这只是偶然删除掉了
情景2
1 2 2 3 4 5
基于上面的情景多出来的偶数就被++跳过了
情景3
1 2 2 3 4 5 6
end()返回finsih
finish–,it++他们继续判断it != v.end()就一直停不下来了,发生了段错误越界
在这里插入图片描述

我们可能会想到以下代码来解决场景3
虽然再Linux里可以跑,但是vs中直接崩溃,它认为erase后it迭代器失效了
在这里插入图片描述
所以stl里的erase和insert一样接受返回值,返回删除后指向的下一个位置
在这里插入图片描述

总结

insert 和 erase的迭代器it使用后认为it都失效
insert可能扩容失效或者不扩容不失效,但你再不同平台下什么时候扩容你是不清楚的,所以都认为insert后迭代器失效!
要想继续使用,需要利用insert 和 erase的返回值

隐藏的浅拷贝问题

在这里插入图片描述

reserve中对于Vector 如果用memcpy按字节拷贝会让新空间的string对象指向旧空间,并且旧空间会被释放,新空间就指向被释放的空间,在析构的时候他们就会析构2次。

解决
可以一个一个对象的拷贝,如果是自定义类型利用赋值重载实现深拷贝,内置类型还是浅拷贝就可以!
在这里插入图片描述
不仅仅是reserve中,拷贝构造中同样需要一个一个拷贝,不然会发生同样析构2次问题
在这里插入图片描述
在这里插入图片描述

vector中指针关系

关于指针 关系判断 < <= 还是 !=
比如链表就没法用< <=
在这里插入图片描述

构造函数模板调用问题

调用n个val的构造反而会调用迭代器区间构造,出现非法的间接寻址问题
非法的间接寻址 目前 指针 迭代器 可解引用 其他不行
说人话就是把10当作迭代器区间*first解引用了,就报错了
在这里插入图片描述

在这里插入图片描述

原因

默认识别类型

在这里插入图片描述

模板匹配规则

能有现成的就吃现成的(原生函数),没有现成的就吃最喜欢的(模板)

在这里插入图片描述

解决

库里面多定义了函数重载,让int类型有现成的可吃,就不会匹配到迭代器区间函数了
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值