【C++模拟实现】vector的模拟实现
【C++模拟实现】vector的模拟实现
目录
- 【C++模拟实现】vector的模拟实现
- vector模拟实现的标准代码
- vector模拟实现中的要点
- insert和erase会涉及到迭代器失效的问题
- vector深度剖析
- 关于模版template< class InputIterator >
- 使用memcpy拷贝问题
作者:爱写代码的刚子
时间:2023.9.1
前言:模拟实现系列好久没更了,前来补更。
vector模拟实现的标准代码
namespace test
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin(){return _start;}const_iterator cend() const{return _finish;}vector():_start(nullptr),_finish(nullptr),_endOfStorage(nullptr){}vector(int n, const T& value = T()){resize(n,value);}template<class InputIterator>vector(InputIterator first, InputIterator last):_start(nullptr),_finish(nullptr),_endOfStorage(nullptr){//存疑,是否要reservewhile(first!=last){push_back(*first);++first;}}vector(const vector<T>& v)//这里是引用:_start(nullptr),_finish(nullptr),_endOfStorage(nullptr){reserve(v.capacity());for(auto e:v){push_back(e);}}vector<T>& operator= (vector<T> v){swap(v);return *this;}~vector(){delete[] _start;_start = nullptr;_finish = nullptr;_endOfStorage = nullptr;}size_t size() const{return _finish - _start;}size_t capacity() const{return _endOfStorage - _start;}void reserve(size_t n){if(n>capacity()) {iterator tmp = new T[n];//拷贝数据(手动)int sz = size();if(_start) {for (int i = 0; i < sz; i++) {tmp[i] = _start[i];}delete[] _start;//一定要记得}_start = tmp;_finish = _start + sz;_endOfStorage = _start + n;}}void resize(size_t n, const T& value = T()){if(n<capacity()){_finish=_start + n;}else{reserve(n);while(_finish!=_start+n){*_finish=value;++_finish;}}}T& operator[](size_t pos){assert(pos<size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos<size());return _start[pos];}void push_back(const T& x){insert(end(),x);}void pop_back(){erase(--end());//注意是--end(),end()指向的是数据的下一个位置}void swap(vector<T>& v){std::swap(v._start,_start);std::swap(v._finish,_finish);std::swap(v._endOfStorage,_endOfStorage);}iterator insert(iterator pos, const T& x){assert(pos>=_start&&pos<=_finish);if(_finish==_endOfStorage){size_t len = pos - _start;size_t newcapacity = capacity()==0?4:capacity()*2;reserve(newcapacity);pos = _start + len;}iterator end = _finish - 1;while(end>=pos){*(end+1) = *end;--end;//--end不是++end()}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos>=_start&&pos<=_finish);iterator it=pos+1;while(it!=_finish){*(it-1)=*it;++it;}--_finish;return pos;}private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾};
}
vector模拟实现中的要点
insert和erase会涉及到迭代器失效的问题
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了 封装,比如:vector的迭代器就是原生态指针T*。因此迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。
有关迭代器失效的几种做法
-
对于vector可能会导致其迭代器失效的操作有:
-
会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、 push_back等。
出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉, 而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。
解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。
-
指定位置元素的删除操作–erase
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。(但Linux下g++可能不一样,因为迭代器使用了原生指针,没有像vs一样进行封装)
-
**迭代器失效解决办法:在使用前,对迭代器重新赋值即可。 **
涉及到底层空间改变时,需要考虑重置迭代器
vector深度剖析

关于模版template< class InputIterator >
为什么不使用自己之前定义的iterator?
- 若使用iterator做迭代器,会导致初始化的迭代器区间[first,last)只能是vector的迭代器
- 重新声明迭代器,迭代器区间[first,last)可以是任意容器的迭代器
使用memcpy拷贝问题
为什么在reserve接口中不能直接使用memcpy进行拷贝?
- memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
- 如果拷贝的是自定义类型的元素,memcpy即高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,memcpy的拷贝实际是浅拷贝。
所以在模版模拟实现中慎用memcpy!!!
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
【附】:范围for是C++11的
相关文章:
【C++模拟实现】vector的模拟实现
【C模拟实现】vector的模拟实现 目录 【C模拟实现】vector的模拟实现vector模拟实现的标准代码vector模拟实现中的要点insert和erase会涉及到迭代器失效的问题vector深度剖析关于模版template< class InputIterator >使用memcpy拷贝问题 作者:爱写代码的刚子 …...
go学习part21(3)redis连接池
连接池 1.介绍 每次使用数据就就建立链接再关闭可以,但是如果有大量客户端频繁请求连接,大量创建连接和关闭会非常耗费资源。 所以就建立一个连接池,里面存放几个不关闭的连接,谁要用就分配给谁。 说明:通过Golang 对 Redis操…...
乐理-笔记
乐理笔记整理 1、前言2、认识钢琴键盘及音名3、升降号、还原号4、如何区分同一音名的不同键?5、各类音符时值的关系6、歌曲拍号7、拍号的强弱规律8、歌曲速度(BPM)9、附点音符10、三连音12、唱名与简谱数字13、自然大调(白键&…...
java八股文面试[数据库]——B树和B+树的区别
B树是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(logn)的时间复杂度进行查找、顺序读取、插入和删除等操作。 1、B树的特性 B树中允许一个结点中包含多个key,可以是3个、4个、5个甚至更多,并不确定,需要看具体的实…...
2、Nginx 安装
文章目录 2、Nginx 安装2.1 官网下载2.2 安装 nginx2.2.1 第一步2.2.2 第二步2.2.3 第三步,安装 nginx2.2.4 第四步,修改防火漆规则 【尚硅谷】尚硅谷Nginx教程由浅入深 志不强者智不达;言不信者行不果。 2、Nginx 安装 2.1 官网下载 nginx…...
最适合 AI 的 Python Web 框架
迷途小书童的 Note 读完需要 4分钟 速读仅需 2 分钟 1 简介 本文将介绍 Gradio 库,它是 Python 的一个 web 框架,可以帮助我们快速构建交互式 AI 应用。我们将了解 Gradio 的应用场景、基本原理、功能介绍,并通过一个代码示例来演示如何使用 …...
算法通关村第十八关——回溯
回溯很大感觉就是多重递归,在递归的题目中,例如斐波那契数列,只需要考虑当前情况以及他的子情况。而在回溯中,要进行很多次递归,并且要对条件进行处理。 LeetCode257:给你一个二叉树的根节点root,按任意顺序ÿ…...
使用kafka还在依赖Zookeeper,kraft模式了解下
Kafka的Kraft模式 概述 Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。其核心组件包含Producer、Broker、Consumer,以及依赖的Zookeeper集群。其中Zookeeper集群是Kafka用来负责集群元数据的管理、控制器…...
【100天精通Python】Day52:Python 数据分析_Numpy入门基础与数组操作
目录 1 NumPy 基础概述 1.1 NumPy的主要特点和功能 1.2 NumPy 安装和导入 2 Numpy 数组 2.1 创建NumPy数组 2.2 数组的形状和维度 2.3 数组的数据类型 2.4 访问和修改数组元素 3 数组操作 3.1 数组运算 3.2 数学函数 3.3 统计函数 4 数组形状操作 4.1 重塑数组形…...
Day01-Java基础语法
目录 1. 人机交互 1.1 什么是cmd? 1.2 如何打开CMD窗口? 1.3 常用CMD命令 1.4 CMD练习 1.5 环境变量 2. Java概述 1.1 Java是什么? 1.2下载和安装 1.2.1 下载 1.2.2 安装 1.2.3 JDK的安装目录介绍 1.3 HelloWorld小案例 2.3.1 …...
代码随想录二刷day06
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣242. 有效的字母异位词二、力扣349. 两个数组的交集三、力扣202. 快乐数四、力扣1两数之和 前言 一、力扣242. 有效的字母异位词 class Solution {pub…...
可扩展的Blender插件开发汇总
成熟的 Blender 3D 插件是令人惊奇的事情。作为 Python 和 Blender 的新手,我经常发现自己被社区中的人们创造的强大的东西弄得目瞪口呆。坦率地说,其中一些包看起来有点神奇,当自我怀疑或冒名顶替综合症的唠叨声音被打破时,很容易想到“如果有人能做出可以做xxx的东西就好…...
2023_Spark_实验二:IDEA安装及配置
一、下载安装包 链接:百度网盘 请输入提取码 所在文件夹:大数据必备工具--》开发工具(前端后端)--》后端 下载文件名称:ideaIU-2019.2.3.exe (喜欢新版本也可安装新版本,新旧版本会存在部分差异) IDEA …...
小赢科技,寻找金融科技核心价
如果说金融是经济的晴雨表,是通过改善供给质量以提高经济质量的切入口,那么金融科技公司,就是这一切行动的推手。上半年,社会经济活跃程度提高背后,金融科技公司既是奉献者,也是受益者。 8月29日࿰…...
NAT与代理服务器
1.DNS Domain Name System 是一整套从域名映射到IP的系统(把域名转化为IP地址) 2.域名简介 3.周鸿祎 傅盛 4.ICMP协议 用来网络故障排查原因 草图理解“位置” ping ICMP 是绕过TCP UDP传输协议的,没有端口号 traceroute 5.NAT技术 N…...
24.排序,插入排序,交换排序
目录 一. 插入排序 (1)直接插入排序 (2)折半插入排序 (3)希尔排序 二. 交换排序 (1)冒泡排序 (2)快速排序 排序:将一组杂乱无章的数据按一…...
Navicat16安装教程
注:因版权原因,本文已去除破解相关的文件和内容 1、在本站下载解压后即可获得Navicat16安装包和破解补丁,如图所示 2、双击“navicat160_premium_cs_x64.exe”程序,即可进入安装界面, 3、点击下一步 4、如图所示勾选“…...
【看表情包学Linux】初识文件描述符 | 虚拟文件系统 (VFS) 初探 | 系统传递标记位 | O_TRUNC | O_APPEND
爆笑教程《看表情包学Linux》👈 猛戳订阅! 💭 写在前面:通过上一章节的讲解,想必大家已对文件系统基本的接口有一个简单的了解,本章我们将继续深入讲解,继续学习系统传递标志位&…...
ssm+vue“魅力”繁峙宣传网站源码和论文
ssmvue“魅力”繁峙宣传网站源码和论文102 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身…...
Linux系统编程5(线程概念详解)
线程同进程一样都是OS中非常重要的部分,线程的应用场景非常的广泛,试想我们使用的视频软件,在网络不是很好的情况下,通常会采取下载的方式,现在你很想立即观看,又想下载,于是你点击了下载并且在…...
OpenClaw+GLM-4.7-Flash:3步实现自动化邮件处理
OpenClawGLM-4.7-Flash:3步实现自动化邮件处理 1. 为什么需要自动化邮件处理? 每天早晨打开邮箱,看到堆积如山的未读邮件时,那种窒息感我太熟悉了。作为技术团队的接口人,我的邮箱常年保持着200未读邮件的状态——有…...
嵌入式开发中PlantUML图表的工程化应用
嵌入式开发中PlantUML图表的工程化应用指南1. 嵌入式文档工具概述在嵌入式系统开发过程中,系统架构图和设计文档是工程师沟通需求、梳理逻辑的核心工具。传统拖拽式绘图工具存在效率低下、维护困难等问题,而基于代码生成图表的PlantUML技术为嵌入式开发文…...
Docker+宝塔双方案:Nextcloud私有云盘从入门到企业级部署全攻略
Nextcloud企业级私有云部署双轨方案:Docker敏捷开发与宝塔生产环境实战指南 在数字化转型浪潮中,企业数据主权意识正在觉醒。Nextcloud作为开源的私有云解决方案,不仅提供了媲美商业云盘的功能体验,更让组织完全掌控数据流向。本文…...
保姆级避坑指南:在openEuler 22.03 LTS上用kubeadm 1.32.2部署K8s集群(含阿里云镜像加速)
保姆级避坑指南:在openEuler 22.03 LTS上用kubeadm 1.32.2部署K8s集群(含阿里云镜像加速) 如果你正在openEuler系统上尝试部署Kubernetes集群,很可能已经踩过不少坑。不同于常见的CentOS或Ubuntu,openEuler作为国产操作…...
从零到一:OpenClaw对接百川2-13B量化模型的完整调试日志
从零到一:OpenClaw对接百川2-13B量化模型的完整调试日志 1. 项目背景与动机 上周在测试本地大模型自动化任务时,发现OpenClaw默认对接的Qwen模型对长文本处理容易截断。正好看到星图平台上线了百川2-13B量化镜像,显存需求仅10GB左右&#x…...
从海报生成实战出发:深度解析Canvas文本绘制的那些“坑”与高效解决方案
从海报生成实战出发:深度解析Canvas文本绘制的那些“坑”与高效解决方案 在数字化营销盛行的今天,一张精美的海报往往能成为内容传播的"门面担当"。无论是文章分享、活动推广还是品牌展示,视觉化呈现的效果直接影响用户点击意愿。…...
保姆级教程:在RHEL 8上彻底搞定X-Server远程连接,让xeyes不再报‘Error can‘t open display‘
深度解析RHEL 8远程X11连接:从原理到实战的全链路解决方案 当你在RHEL 8服务器上尝试通过SSH转发X11图形界面时,是否遇到过xeyes测试程序报出"Error: Cant open display"的困扰?这看似简单的错误背后,实际上隐藏着新版R…...
Qwen3-ASR-1.7B实战教程:curl命令行调用API实现无人值守识别任务
Qwen3-ASR-1.7B实战教程:curl命令行调用API实现无人值守识别任务 1. 课程目标与价值 本教程将教你如何使用curl命令行工具调用Qwen3-ASR-1.7B语音识别模型的API接口,实现自动化、无人值守的语音转文字任务。学完本教程,你将能够:…...
Batex:Blender批量FBX导出终极指南,3D艺术家必备的高效工作流解决方案
Batex:Blender批量FBX导出终极指南,3D艺术家必备的高效工作流解决方案 【免费下载链接】batex Export selected objects as fbx in batch operation 项目地址: https://gitcode.com/gh_mirrors/ba/batex 还在为Blender中繁琐的单个模型导出而烦恼…...
从零到一:构建高性能Infiniband/RDMA集群的实践指南
1. Infiniband与RDMA技术基础 第一次接触Infiniband时,我被它惊人的性能数据震撼到了——200Gbps的传输速率,微秒级的延迟,这完全颠覆了我对传统以太网的认知。简单来说,Infiniband就像是为数据中心量身定制的高速公路,…...
