当前位置: 首页 > 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和代理服务器…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...