转解疑难杂症,详解vector迭代器失效和深浅拷贝的问题

news/2024/11/15 14:27:53/

前文

http://t.csdn.cn/kVeVX——vector模拟实现
本篇文章主要是针对vector中的两个比较经典的问题同时也是上一篇文章遗留下来的问题进行详细解释,第一个就是迭代器失效的问题,第二个是深浅拷贝的问题
ps:注意本文演示用的代码是上一篇vector模拟实现的代码,而不是库中的。

一,迭代器失效

vector失效的问题注意发生在insert()和erase()中,由于两个发生的原因不尽相同,所以我们分开来讲

1.1 insert()中迭代器失效的问题

如上,是我们实现的插入函数的代码

这时候就要问铁子们一个问题了,上述程序运行会发生什么?
相信各位聪明的老铁已经看出来了,没错报错了,报错的原因呢,源自于insert中的assert,由此我们发现pos已经不属于_start至_finsh的范围了,此时pos失效,为什么呢?
如上左图图所示,在insert()中我们新开了个空间,由于我们及时更新了insert()中的pos,所以insert()中的pos也指向了新空间,但是右图test6中的pos改变了吗?没有,右图的pos指向的仍然是旧空间,所以就发生了迭代器失效的问题。
解决办法:将insert()更新后的pos返回

1.2 erase()中迭代器失效的问题

上面是我们写的erase的代码
下面我们看下面的问题
如图为什么我们第二次调用erase失效了,失效的原因也是不属于[_start,_finsh),为什么?
因为当我们要删除的数据是最后一个有效数据时,删除后,pos所指向的地方已经不合法,所以失效,当然如果没有这个assert,会实现吗?
大家可以看到实现了,但是这和pos没有关系,这里是因为erase中_finsh--导致的。
eraser迭代器失效的问题就是,在删除后,pos所指向的数据已经不是我们原来想要删除的东西了。

1.3 总结

总的来说,vector迭代器失效的原因主要是对vector进行插入或删除操作时,导致vector的内存重新分配原有的迭代器指向的内存地址不再是有效的,因此迭代器失效。
这里我们虽然有解决办法,但是尽量还是不要在使用pos.

二,深浅拷贝的问题

这里涉及到深浅拷贝问题主要是因为vector中存储的有可能是自定义类型如
如上图所示如果使用memcpy也就是浅拷贝进行拷贝的话,这样真正深拷贝到的只有vector也就是第一层,而其内部第二层,string仍是浅拷贝,因此两个vector中的string是完全相同的,指向的也是同一块空间,所以在析构是会发生重复析构导致出错,平时也会因为共享空间资源导致漏洞百出。

解决办法如下:
对于vector中的数据进行一个一个赋值来解决
        //拷贝构造vector(const vector<V>& v){_start = new V[v.capacity()];//memcpy(_start, v._start, sizeof(V) * v.size());for (int i = 0; i < v.size(); i++){_start[i] = v._start[i];}_finsh = _start + v.size();_end_of_storage = _start = v.capacity;}

但是我们之前模拟的vector并没有写赋值重载,我们这里完善一下。

实现逻辑:我们可以用swap函数来实现,但是需要注意这里传参不能是引用传,只能传值,这样属于创建了一个临时vector进行交换,这样交换了也不会对原来的vector有影响

//赋值重载vector<V>& operator=(vector<V> v){swap(v);return *this;}

总结

到这里vector算是告一段落,后续我们会进行链表的讲解,敬请期待。

http://www.ppmy.cn/news/32792.html

相关文章

基于springboot+vue的“智慧食堂”程序【毕业论文,源码】

系统登录界面系统架构开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven浏览器&#xf…

Linux驱动开发

一、驱动分类Linux中包含三大类驱动&#xff1a;字符设备驱动、块设备驱动和网络设备驱动。其中字符设备驱动是最大的一类驱动&#xff0c;因为字符设备最多&#xff0c;从led到I2C、SPI、音频等都属于字符设备驱动。块设备驱动和网络设备驱动都要比字符设备驱动复杂。因为其比…

C实现带头循环双向链表(pushback pushfront popback popfront insert erase find destroy等)

带头循环双向链表是链表中效率最高的&#xff0c;但是由于他里面有两个指针节点&#xff0c;所以也会更浪费空间一些&#xff0c;但是他在任意位置的插入删除的效率很高&#xff0c;所以也就弥补了顺序表的不足。 首先我们来看一下他的逻辑结构是什么样子的 下面我们看一下如何…

【面试题】Python软件工程师能力评估试题(一)

文章目录前言应试者需知&#xff08;一&#xff09;Python 语言基础能力评估1、理解问题并完成代码&#xff1a;2、阅读理解代码&#xff0c;并在空白处补充完整代码&#xff1a;3、编写一个装饰器&#xff1a;exposer4、阅读代码并在空白处补充完整代码&#xff1a;5、自行用P…

5 全面认识java的控制流程

全面认识java控制流程1.块作用域2.条件语句3.迭代语句3.1while语句3.2do-while语句3.3for语句3.4 for-in语法4.中断控制流程的语句4.1 return4.2 break和continue4.2.1 不带标签的break语句4.2.2 带标签的break语句4.2.3 continue语句4.3 goto()5.多重选择:switch语句1.块作用域…

小米10s格机修复 nv报错案例解析 关于基带分区的一些常识

前面分享过几期关于基带 diag端口与qcn相关的几篇帖子。其中一位粉丝朋友联系我。他的机型因为误格机导致手机进不去系统&#xff0c;反复进入官方rec报错nv损坏。进不去系统。 有兴趣的朋友可以参阅我的几个帖子&#xff0c;只是个人的一些片面理解。 基带相关贴; 安卓玩机…

进程跟线程的区别

进程跟线程的区别 文章目录进程跟线程的区别前言一.什么线程二.线程与进程的联系三.线程与进程有什么不同前言 现代所有计算机都能同时做几件事情,当一个用户程序正在运行时,计算机还能同时读取磁盘,并向屏幕打印输出正文.在一个多道操作程序中,cpu由一道程序向另外一道程的切…

【HTML系列】前章 · HTML前序知识

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…