当前位置: 首页 > news >正文

【C++】——vector模拟实现和迭代器失效问题

文章目录

  • 模拟实现
    • vector基本成员变量
    • vector的构造与析构
    • vector迭代器
    • vector容量
    • vector元素访问
    • vector修改操作
  • vector迭代器失效问题
    • 什么是迭代器失效
      • 1.插入元素导致迭代器失效
      • 2.删除元素导致迭代器失效
      • 3.重新分配空间导致迭代器失效
    • 如何解决迭代器失效问题

模拟实现

vector基本成员变量

在这里插入图片描述

namespace sg
{template<class T>class vector{
public:typedef T* iterator;typedef const T* const_iterator;
private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;}
};

这里我把成员改成与迭代器相关,更方便我们接下来的使用

vector的构造与析构

//构造函数
vector(const vector<T>& v)
{reserve(v.size()); // 开辟一个空间for (auto& e : v){push_back(e);}
}
//析构函数
~vector()
{if (_start) // 如果_start不为空就析构{delete[] _start;_start = _finish = _end_of_storage = nullptr;}
}

vector迭代器

iterator begin()
{return _start;
}
iterator end()
{return _finish;
}
const_iterator begin() const
{return _start;
}
const_iterator end() const
{return _finish;
}

vector容量

bool empty()
{return _start == _finish;
}
void reserve(size_t n)
{size_t old_size = size();T* tmp = new T[n];memcpy(tmp, _start, size() * sizeof(T));delete[] _start;_start = tmp;_finish = tmp + old_size;_end_of_storage = _start + n;
}
size_t size()
{return _finish - _start;
}size_t capacity()
{return _end_of_storage - _start;
}void resize(size_t n, T val = T())
{if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}
}

vector元素访问

T& operator[](size_t i)
{assert(i < size());return _start[i];
}

vector修改操作

void push_back(const T& x)
{if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;_finish++;
}
void pop_back()
{assert(!empty());--_finish;
}
iterator insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);//扩容if (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;
}
void erase(iterator pos)
{assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it != end()){*(it - 1) = *it;++it;}--_finish;
}

vector迭代器失效问题

迭代器失效的本质是因为vector的内存管理机制和对动态数组的封装方式。vector的某些操作会导致其底层数组的重新分配,所以原有的迭代器会失效。

什么是迭代器失效

迭代器失效的常见情况:

  1. 插入元素:在vector末尾插入元素,除了指向最后一个元素的迭代器以外,其他迭代器依旧有效
    如果在其他位置插入,则指向该插入位置的迭代器和其之后的所有迭代器失效
  2. 删除元素:删除元素后,被删除和删除之后的所有迭代器都会失效
  3. 重新分配:当vector的大小超过当前容量时,它可能分配需要更大的空间进行存储元素,这种重新分配会导致所有迭代器、指针、引用失效

注意:vector的迭代器失效也和编译器环境有关,有关指报错和运行。在Linux下,g++对于迭代器失效的检查就没这么严格,一般迭代器失效也还能运行,不过运行结果会出错。

1.插入元素导致迭代器失效

int main()
{vector<int> v1{ 1,2,3,4,5 };auto it = v1.begin();v1.insert(v1.begin(), 99); // 在第一个位置插入元素while (it != v1.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

在这里插入图片描述
插入和删除同理,这里我已删除为例
在这里插入图片描述

2.删除元素导致迭代器失效

int main()
{vector<int> v1{ 1,2,3,4,5 };auto it = v1.begin();v1.erase(v1.begin()); // 删除第一个元素while (it != v1.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

在这里插入图片描述

3.重新分配空间导致迭代器失效

int main()
{vector<int> v1{ 1,2,3,4,5 };auto it = v1.begin();v1.resize(20, 10); // 容量不够,重新分配空间,又叫异地扩容while (it != v1.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

如何解决迭代器失效问题

string迭代器失效原因和vector异地扩容类似,需要注意。

解决办法:在使用前重新赋值

int main()
{vector<int> v1{ 1,2,3,4,5 };auto it = v1.begin();v1.resize(20, 10); // 容量不够,重新分配空间,又叫异地扩容it = v1.begin(); // 使用前重新赋值while (it != v1.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

在这里插入图片描述

相关文章:

【C++】——vector模拟实现和迭代器失效问题

文章目录 模拟实现vector基本成员变量vector的构造与析构vector迭代器vector容量vector元素访问vector修改操作 vector迭代器失效问题什么是迭代器失效1.插入元素导致迭代器失效2.删除元素导致迭代器失效3.重新分配空间导致迭代器失效 如何解决迭代器失效问题 模拟实现 vector…...

USB 3.1 标准 A 型连接器及其引脚分配

USB 3.1 标准 A 型连接器 USB 3.1 标准 A 型连接器被定义为主机连接器。它具有与 USB 2.0 标准 A 型连接器相同的配合接口&#xff0c;但增加了另外两对差分信号和一个接地引脚。 USB 3.1 标准 A 型插座可以接受 USB 3.1 标准 A 型插头或 USB 2.0 标准 A 型插头。类似地&…...

机器学习文献|基于循环细胞因子特征,通过机器学习算法预测NSCLC免疫治疗结局

今天我们一起学习一篇最近发表在Journal for immunotherapy of cancer &#xff08;IF 10.9&#xff09;上的文章&#xff0c;Machine learning for prediction of immunotherapeutic outcome in non-small-cell lung cancer based on circulating cytokine signatures[基于循环…...

Qt 实现自定义截图工具

目录 Qt 实现自定义截图工具实现效果图PrintScreen 类介绍PrintScreen 类的主要特性 逐步实现第一步&#xff1a;类定义第二步&#xff1a;初始化截图窗口第三步&#xff1a;处理鼠标事件第四步&#xff1a;计算截图区域第五步&#xff1a;捕获和保存图像 完整代码PrintScreen.…...

第15-05章:获取运行时类的完整结构

我的后端学习大纲 我的Java学习大纲 6.1.第一组方法API: 1.API列表&#xff1a;java.lang.Class 类&#xff1a; 2.代码测试&#xff1a; public class ReflectionUtils{ puvblic static void main(String[] args){}// 第一组Testpublic void api_01{//上面截图的代码......…...

【Kubernetes】K8s 的鉴权管理(二):基于属性 / 节点 / Webhook 的访问控制

K8s 的鉴权管理&#xff08;二&#xff09;&#xff1a;基于属性 / 节点 / Webhook 的访问控制 1.基于属性的访问控制&#xff08;ABAC 鉴权&#xff09;2.基于节点的访问控制&#xff08;node 鉴权&#xff09;2.1 读取操作2.2 写入操作 3.基于 Webhook 的访问控制3.1 基于 We…...

Java面试、技巧、问题、回复,资源面面观

入门 先了解一下面试流程 复习 Java 基础知识&#xff1a; 温习 Java 编程的核心概念&#xff0c;包括数据类型、变量、循环、数组和面向对象的编程原则。数据结构和算法&#xff1a; 加强您对 Java 编程中使用的基本数据结构和算法的理解。练习编码&#xff1a; 在各种平台上解…...

深入理解Elasticsearch的`_source`字段与索引优化

在Elasticsearch (ES) 中&#xff0c;_source字段是一个关键组件&#xff0c;它不仅决定了数据的存储方式&#xff0c;还影响到查询时返回的内容。在某些场景下&#xff0c;我们可以通过配置_source来优化存储和性能&#xff0c;尤其是当我们希望减少存储空间或避免返回某些字段…...

Pikachu靶场

先来点鸡汤&#xff0c;少就是多&#xff0c;慢就是快。 环境搭建 攻击机kali 192.168.146.140 靶机win7 192.168.146.161 下载zip&#xff0c;pikachu - GitCode 把下载好的pikachu-master&#xff0c;拖进win7&#xff0c;用phpstudy打开网站根目录&#xff0c;.....再用…...

TS axios封装

方式一 service/request/request.ts import axios from axios import { ElLoading } from element-plus import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from axios import type { ILoadingInstance } from element-plus/lib/el-loading/src/loading.typ…...

学会使用西门子博途Startdrive中的测量功能

工程师在驱动调试过程中&#xff0c;往往需要对驱动系统的性能进行分析及优化&#xff0c;比如说借助于调试软件中的驱动器测量功能&#xff0c;可以得到驱动系统的阶跃响应、波特图等&#xff0c;以此为依据工程师可以调整速度控制器、电流控制器的相关参数&#xff0c;使驱动…...

Spring Security认证与授权

1 Spring Security介绍 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统中的一员&#xff0c;因此它伴随着整个Spring生态系统不断修正、升级&#xff0c;在spring boot项目中加入springsecurity更是…...

速通GPT:Improving Language Understanding by Generative Pre-Training全文解读

文章目录 速通GPT系列几个重要概念1、微调的具体做法2、任务感知输入变换3、判别式训练模型 Abstract概括分析和观点1. 自然语言理解中的数据问题2. 生成预训练和监督微调的结合3. 任务感知输入变换4. 模型的强大性能 Introduction概括分析和观点1. 自然语言理解的挑战在于对标…...

软件质量保证例题

答案&#xff1a;D 软件质量保证 功能性 适合性 准确性 互操作性 安全保密性 依从性 可靠性 成熟性 容错性 易恢复性 易用性 易理解性 易学性 易操作性 效率 时间特性 资源利用性 维护性 易分析性 易改变性 稳定性 易测试性 可移植性 适应性 易安装性 一致性 易替换…...

动态规划算法---04.斐波那契数列模型_解码方法_C++

题目链接&#xff1a;91. 解码方法 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/decode-ways/description/ 一、题目解析 题目&#xff1a; 题目大意&#xff1a;从题目中我们可以知道&#xff0c;解码就是在字符串s中由‘1’到‘26’的字符可以转化…...

crm如何做私域运营?

流量获取的挑战日益增加&#xff0c;客户线索成本高、客户资源流失严重、转化率低&#xff0c;因此&#xff0c;私域流量管理已成为关键。 当前挑战 1、公域流量难以整合&#xff1a;外部流量分散&#xff0c;难以有效汇总和沉淀。 2、私域运营体系缺失&#xff1a;缺乏有效沟…...

基于QGIS 3.16.0 的OSM路网矢量范围裁剪实战-以湖南省为例

目录 前言 一、相关数据介绍 1、OMS路网数据 2、路网数据 3、路网图层属性 二、按省域范围进行路网裁剪 1、裁剪范围制定 2、空间裁剪 3、裁剪结果 三、总结 前言 改革开放特别是党的十八大以来&#xff0c;我国公路发展取得了举世瞩目的成就。国家高速公路网由“7 射…...

WPF 手撸插件 八 依赖注入

本文内容大量参考了&#xff1a;https://www.cnblogs.com/Chary/p/11351457.html 而且这篇文章总结的非常好。 1、注意想使用Autofac&#xff0c;Autofac是一个轻量级、‌高性能的依赖注入&#xff08;‌DI&#xff09;‌框架&#xff0c;‌主要用于.NET应用程序的组件解耦和…...

走进低代码报表开发(一):探秘报表数据源

在前文当中&#xff0c;我们对勤研低代码平台的流程设计功能进行了介绍。接下来&#xff0c;让我们一同深入了解在企业日常运营中另一个极为常见的报表功能。在当今数字化时代&#xff0c;高效的报表生成对于企业的决策至关重要。勤研低代码开发平台能够以卓越的性能和便捷的操…...

代理服务器及其原理

代理服务器的代理可以分为正向代理和反向代理&#xff0c;本篇将讲解这两种代理方式的原理&#xff0c;以及对应的功能特点和应用场景。最后还对比和 NAT 和代理服务器的区别。 目录 正向代理 工作原理 功能特点 应用场景 反向代理 基本原理 应用场景 NAT和代理服务器…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...