【C++】vector的迭代器失效问题深浅拷贝

vector的迭代器失效问题&深浅拷贝

  • 一,vector迭代器失效问题
    • 1. 什么是迭代器失效
    • 2. insert()导致的迭代器失效问题
    • 3. 解决办法
    • 4. erase() 导致的迭代器失效问题
    • 5. 解决办法
  • 二,深浅拷贝问题
    • 1. 什么是深浅拷贝问题
    • 2.reserve的深度解析
    • 3.解决办法

一,vector迭代器失效问题

1. 什么是迭代器失效

先说一下什么是迭代器失效
迭代器失效本质上来讲,就是在插入和删除后pos所指的位置不是更新后的位置,而是原来的位置。


2. insert()导致的迭代器失效问题

insert可能会导致迭代器失效,这是因为当插入数据需要扩容时,返回的pos位置还是原来的那块地址,但是扩容后插入的位置已经发生了变化,所以会导致迭代器失效。
在这里插入图片描述

3. 解决办法

为了解决这种问题,所以vector的insert在其完成插入操作后会返回其更新后的迭代器位置。
在这里插入图片描述
在这里插入图片描述


4. erase() 导致的迭代器失效问题

erase也可能会导致迭代器失效
看下面的场景:
如果要删除vector中每个偶数,

vector<int> v{1,2,2,3,4,5,6,7};
vector<int>::iterator it = v.begin();
while(it != v.end()){if(*it % 2 == 0){it = v.erase(it);}++it;
}

这里会出现第二个2没有被删除的情况,原因如下:

在这里插入图片描述

5. 解决办法

要解决这样的问题,我们可以让 it++ 只在不是偶数的时候操作

vector<int> v{1,2,2,3,4,5,6,7};
vector<int>::iterator it = v.begin();
while(it != v.end()){if(*it % 2 == 0){it = v.erase(it);}else{++it;	}}

二,深浅拷贝问题

1. 什么是深浅拷贝问题

假设有这样一个场景,当vector要发生拷贝构造时,如果我们按照常规的写法来写拷贝构造:

myvector(const myvector<T>& v) {//拷贝构造_start = new T[v.capacity()];memcpy(_start, v._start, sizeof(T) * v.size());_finish = _start + v.size();_end_of_storage = _start + v.capacity();
}

当进行拷贝构造时,被拷贝的数据是个二维数组时,就会出现两次析构的问题

vector<vector<int>> vv1{{1,2},{3,4}};//vv1是一个两行两列的二维数组
vector<vector<int>> vv2(vv1);

具体原因看下图:

memcpy只是按照字节进行 浅拷贝vv1的_start只是拷贝给了vv2的_start,但是没有将其所指向的这个二维数组拷贝给vv2
在这里插入图片描述

所以对vv1和vv2进行析构时,会对同一块二维数组这个空间进行两次释放。

2.reserve的深度解析

从上面我们得知了memcpy造成的深浅拷贝问题后,我们来剖析一下reserve,其实reserve其实也是深浅拷贝的问题
如果我们要开辟的空间大于其实际长度,那么就要重新开辟空间,再将原来空间的数据存放到现在的空间中,如果我们继续使用memcpy来进行拷贝的话,那么当vector中存放的是自定义的数据时,memcpy只是浅拷贝,和上述拷贝构造问题一样会出现二次析构的问题。

以下是使用了memcpy的reserve:

void reserve(size_t n) {if (n > capacity()) {T* tmp = new T[n];size_t old = size();//保存之前的有效长度if (_start) {memcpy(tmp, _start, sizeof(T) * old);//注意:这里memcpy是浅拷贝,如果T为自定义类型,会造成两次析构}_start = tmp;_finish = _start + old;_end_of_storage = _start + n;}
}

3.解决办法

要解决深浅拷贝问题,我们可以将原来空间中的数据依次插入到新的空间中,而不是使用memcpy


解决拷贝构造浅拷贝问题:

myvector(const myvector<T>& v) {reserve(v.capacity());for (auto e : v) {push_back(e);}
}

解决reserve的浅拷贝问题:

其实也是一个个赋值给新的空间来避免浅拷贝

void reserve(size_t n) {if (n > capacity()) {T* tmp = new T[n];size_t old = size();//保存之前的有效长度if (_start) {//memcpy(tmp, _start, sizeof(T) * old);//注意:这里memcpy是浅拷贝,如果T为自定义类型,会造成两次析构for (size_t i = 0; i < old; i++) {tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + old;_end_of_storage = _start + n;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/522841.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

绝赞春招拯救计划

huihut/interview: &#x1f4da; C/C 技术面试基础知识总结&#xff0c;包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。This repository is a summary of the basic knowledge of recruiting job seekers and beginners in t…

【linuxC语言】dup、dup2函数

文章目录 前言一、dup函数二、dup2函数三、将标准输出重定向到文件总结 前言 在Linux环境下&#xff0c;dup、dup2以及原子操作都是用于文件描述符管理和处理的重要工具。这些功能提供了对文件描述符进行复制和原子操作的能力&#xff0c;使得在多线程或多进程环境中更加安全和…

Redis缓存预热-缓存穿透-缓存雪崩-缓存击穿

什么叫缓存穿透? 模拟一个场景: 前端用户发送请求获取数据,后端首先会在缓存Redis中查询,如果能查到数据,则直接返回.如果缓存中查不到数据,则要去数据库查询,如果数据库有,将数据保存到Redis缓存中并且返回用户数据.如果数据库没有则返回null; 这个缓存穿透的问题就是这个…

Hotchips2018年-英伟达V100展示肌肉(未来芯片论坛及资料下载)

HOTCHIPS是什么&#xff1f; HOTCHIPS是一个关于计算机体系结构和电子设计的会议&#xff0c;主要探讨芯片设计、存储器、能源效率、机器学习和人工智能等方面的发展。该会议每年都会召开一次&#xff0c;吸引着来自世界各地的专业人士和研究人员。 在HOTCHIPS 2018年会上&a…

Go语言物联网开发安科瑞ADW300/4G电能表数据上传mqtt平台-电表接线到传输数据完整流程

电能表功能说明 ADW300是方便用户进行用电监测、集抄和管理&#xff0c;可灵活安装在配电箱中&#xff0c;可用于电力运维、环保监管等在线监测类平台中。我们本案例是用于工业售电公司对出售电的管理&#xff0c;设备可以监控用电情况、故障监控及警报&#xff0c;售电公司可…

新一代信息技术下,AI如何重塑售前工作

近期&#xff0c;“新质生产力”一词犹如一颗璀璨的新星&#xff0c;频繁地在各大媒体平台上抢占热点位置&#xff0c;引发了大家的关注。关于“新质生产力”官方的解释是科技创新驱动经济高质量发展的必然产物&#xff0c;它代表着新一轮科技革命和产业变革的重要方向。 在今…

力扣:链表相交、环形链表、环形链表||

力扣 面试题 02.07.链表相交 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&…

探索精酿啤酒与西式甜点的浪漫搭配

在繁忙的都市生活中&#xff0c;总有那么一些时刻&#xff0c;我们需要放慢脚步&#xff0c;享受那份与众不同的浪漫与宁静。而Fendi Club啤酒与西式甜点的搭配&#xff0c;正是为这些时刻量身定制的。它们以其与众不同的口感和风味&#xff0c;为人们带来了一场味蕾的盛宴&…

Redis进阶(三):主从复制

为了解决单点问题&#xff0c;实现多服务器部署redis&#xff0c;有几种解决方案可以实现&#xff1a;主从复制&#xff0c;主从哨兵还有集群。 何为主从复制 简单来说有三个服务器分别部署了redis-server程序&#xff0c;选中一个服务器当作主节点&#xff0c;其他的就是从节…

2024 批量下载公众号文章内容/阅读数/在看数/点赞数/留言数/粉丝数导出pdf文章备份(带留言):公众号记忆承载近1500篇历史文章在线查看,找文章方便了

关于公众号文章批量下载&#xff0c;我之前写过很多文章&#xff1a; 视频更新版&#xff1a;批量下载公众号文章内容/话题/图片/封面/音频/视频&#xff0c;导出html&#xff0c;pdf&#xff0c;excel包含阅读数/点赞数/留言数 2021陶博士2006/caoz的梦呓/刘备我祖/六神读金…

方阵的特征值与特征向量

目录 特征值 & 特征向量 相关性质 特征值 & 特征向量 相关性质

项目解决方案:多地5G蓄能电站的视频监控联网系统设计方案

目 录 一、前言 二、系统架构设计 1、系统架构设计说明 2、系统拓扑图 三、关键技术 1. 5G支持技术 2. 视频图像处理技术 3. 数据融合与分析技术 四、功能特点 1. 高效可靠 2. 实时监测 3. 远程控制 4. 故障预测 五、应用前景 一、前言 随着能源…