【vector模拟实现】附加代码讲解
vector模拟实现
- 一、看源代码
- 简单实现
- 1. push_back
- capacity(容量)
- size
- reserve(扩容)
- operator[ ] (元素访问)
- 2. pop_back
- 3. itorator(迭代器)
- 4.insert & erase (头插头删)
- 5. 拷贝构造和析构函数
- default关键字(强制编译器生成)
- 其他问题
一、看源代码
- 在我们自己实现 vector 的时候,我们可以参考 vector 的源代码

- 大致功能初步了解
-
- 成员变量
-
- 核心成员函数
- 根据名字连蒙带猜,通过时间看源码细节确认
我们自定义的成员变量:
template<class T>
class vector
{
public:private:T* _a;size_t _size;size_t _capacity;
};
修改后:
namespace bit //同一个域内,就不会和编译器里面的vector弄混
{template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;};
}
简单实现
前情提要:我们分离定义不分离是因为分离会出现连接问题,这个我们后面会提到
1. push_back

下面是push-back的大致框架:
void push_back(const T& x)
{//如果满了就扩容if(_finish == _end_of_storage){//扩容}
}
注意:在这里我们还要实现三个前提函数:capacity()、size()、reserve()
capacity(容量)
size_t capacity()
{return _end_of_storage - _start;
}
size
size_t size()
{return _finish - _start;
}
reserve(扩容)
void reserve(size_t n)
{//直接扩容if (n > capacity()){T* tmp = new T[n]; //开辟空间memcpy(tmp, _start, sizeof(T) * size()); //拷贝delete[] _start; //释放旧空间_start = tmp; //指向新空间}_finish = _start + size();_end_of_storage = _start + n;
}
⭐通过以上代码,我们就可以开始实现👇
void push_back(const T& x)
{//如果满了就扩容if (_finish == _end_of_storage){//如果capacity 是 0 那么就给四个空间,不是就乘二倍size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = x;++_finish;
}

operator[ ] (元素访问)
T& operator[](size_t i)
{assert(i < size());//断言检查越界情况return _start[i];
}
问题一:测试会发现,我们没有包iostream头文件,所以cout无法使用

- 这里就涉及到一个问题 头文件 .h 在 .cpp 文件里面会展开
所以当我们在Test.cpp里面展开vector.h时,又可以使用了

- 因为展开时他会向上查找


但但但是,又有一个问题,运行报错了

- 空指针问题,通过测试,我们可以发现的是,size算法出现问题
start 是新的 但是 finish 是旧的
当我们重新扩容之后,_start == tmp , 而_ finish还是原来的那个t

- 修改后代码如下:
void reserve(size_t n)
{//直接扩容if (n > capacity()){size_t oldsize = size();T* tmp = new T[n]; //开辟空间if (_start) {memcpy(tmp, _start, sizeof(T) * size()); //拷贝delete[] _start; //释放旧空间 }_start = tmp; //指向新空间_finish = tmp + oldsize;_end_of_storage = _start + n;}}
2. pop_back
那么这个就比较简单了,代码实现如下👇:
void pop_back()
{assert(size() > 0);--_finish
}
3. itorator(迭代器)
- 在没有迭代器的情况下时,我们是不能使用范围for的

迭代器代码实现👇
typedef T* iterator;
iterator begin()
{return _start;
}
iterator end()
{return _finish;
}

- 当然,也有const迭代器
是指迭代器指向的内容不可修改
typedef const T* const_iterator;iterator begin() const
{return _start;
}
iterator end() const
{return _finish;
}
4.insert & erase (头插头删)

void test_vector3()
{bit::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.insert(v1.begin(), 0); //头插v1.erase(v1.begin()); //头删
}
运行结果:

⭐insert的的实现
void insert(iterator pos, const T& x)
{if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;
}
注意:这里的扩容会导致迭代器失效,本质上也是一种野指针,pos指向的位置已经失效了

- 所以我们只需要将pos指向新空间对应的位置就好

修改后的insert👇
void insert(iterator pos, const T& x)
{if (_finish == _end_of_storage){size_t len = pos - _start; //加上这一句计算pos的位置size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len; //重置为新pos的位置}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;
}
- 紧接而来的问题,当我们调用自己写insert时,pos会失效,使得在后面不能重新在调用pos
insert(pos,100);
erase的实现代码👇
void erase(iterator pos)
{assert(pos >= _start);assert(pos <= _finish);iterator it = pos + 1;while (it != _finish){*(it - 1) = *it;**it;}--_finish;
}
- 当我们使用erase但是也会出现失效的可能性,这也说明迭代器失效不只是野指针的问题

- 这取决于VS的编译器对于iterator,我们出了作用域时,会类似标记为 false ,此时再次调用,就会报错

5. 拷贝构造和析构函数
- 拷贝构造
问题一:如果我们不写拷贝构造的话,在VS里面默认是什么
在内置类型里面,我们完成的是值拷贝,也就是所谓的浅拷贝,这不是我们所需要的


拷贝构造函数代码如下👇
void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}// v1 = v3
vector<T>& operator=(vector<T>& v)
{this->swap(v);return *this;
}
//v2(v1)
vector(const vector<T>& v)
{for (auto e : v){push_back(e);}
}//但是现在并没有写构造
- 但是在这里并没有运行,所以在这里我们需要提前了解一下关键字
default关键字(强制编译器生成)
//强制编译器生成默认的
vector() = dafault;
析构函数代码如下👇
~vector()
{if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}
}
其他问题
- 有人在编译的时候可能会出现内部编译器出错
- 因为有模板的原因,编译器报错比较混乱
- 一般都是少了分号的原因
- 可以用分段注释的方法来解决

相关文章:
【vector模拟实现】附加代码讲解
vector模拟实现 一、看源代码简单实现1. push_backcapacity(容量)sizereserve(扩容)operator[ ] (元素访问) 2. pop_back3. itorator(迭代器)4.insert & erase (头插…...
本地运行ChatTTS
TTS 是将文字转为语音的模型,最近很火的开源 TTS 项目,本地可以运行,运行环境 M2 Max,差不多每秒钟 4~~5 个字。本文将介绍如何在本地运行 ChatTTS。 下载源码 首先下载源代码 git clone https://github…...
应用解析 | 面向智能网联汽车的产教融合解决方案
背景介绍 随着科技的飞速发展,智能网联汽车已成为汽车产业的新宠,引领着未来出行的潮流。然而,行业的高速发展也带来了对高素质技术技能人才的迫切需求。为满足这一需求,推动教育链、人才链与产业链、创新链的深度融合࿰…...
华为设备动态路由OSPF(单区域+多区域)实验
动态路由OSPF的配置 OSPF分类两种情况:单区域 多区域路由 OSPF单区域路由配置 OSPF:开放最短路径优先的路由协议。属于大型动态路由协议,适用于中大型的园区网。 网络拓扑: 配置步骤: 1.完成基本配置(略&a…...
R语言探索与分析19-CPI的分析和研究
一、选题背景 CPI(居民消费价格指数)作为一个重要的宏观经济指标,扮演着评估通货膨胀和居民生活水平的关键角色。在湖北省这个经济活跃的地区,CPI的波动对于居民生活、企业经营以及政府宏观经济政策制定都具有重要的影响。因此&a…...
【C++ | 拷贝构造函数】一文了解C++的 拷贝(复制)构造函数
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰:2024-06-07 2…...
【工具】Vmware17 安装mac(13.6.7)虚拟机
目录 0.简介 1.环境 2.详细步骤 2.1下载mac镜像(可以选择你所需要的) 2.2 VMware安装 1)创建新的虚拟机 2)选择【典型】,点击下一步 3)选择【安装程序光盘映像文件】,点击浏览ÿ…...
mac node版本切换 nvm install nvm ls-remote N/A问题
mac 使用nvm 切换node版本失败或者 nvm install &nvm ls-remote N/A问题 一、出现情况 输入 nvm install v16.18.0输出结果 Version 16.18.0 not found try nvm is-remote•to browse available versions.输入 nvm ls-remote输出结果 N/A二、原因分析 1. 镜像包获取…...
牛客小白月赛95
vp,为后面的比赛做准备 A.相遇 #include <iostream> #include <vector> #include <algorithm> #include <set> #include <unordered_map> #include <cstring> #include <cstdio> #include <string> #include <…...
Python实现调用并执行Linux系统命令
😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 🤓 同时欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深…...
古字画3d立体在线数字展览馆更高效便捷
在数字时代的浪潮中,大连图书馆以崭新的面貌跃然屏幕之上——3D全景图书馆。这座承载着城市文化精髓与丰富知识资源的数字图书馆,利用前沿的三维建模技术,为我们呈现了一个全新的知识世界。 随时随地,无论您身处何地,只…...
编写程序,提示用户输入以米/秒(m/s)为单位的速度v和以米/秒的平方(m/s)为单位的加速度 a,然后显示最短跑道长度。
(物理:求出跑道长度)假设一个飞机的加速度是a而起飞速度是v,那么可以使用下 面的公式计算出飞机起飞所需的最短跑道长度: 编写程序,提示用户输入以米/秒(m/s)为单位的速度v和以米/秒的平方(m/s)为单 位的加速度 a,然后显示最短跑道长度。下面…...
k8s 对外发布(ingress)
在k8s中,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制; 对集群外部,他类似负载均衡器,可以在集…...
FL Studio21.2.7最新中文破解版免费激活,音乐制作全掌握!
在数字音乐制作的海洋中,你是否曾因软件的复杂操作、高昂费用而望而却步?是否梦想拥有一款既强大又亲民的音乐制作工具,让你的创作激情不受束缚?今天,让我们一起探索FL Studio21——这款官方中文破解激活码及免费版下载…...
2 - 寻找用户推荐人(高频 SQL 50 题基础版)
2.寻找用户推荐人 考点: sql里面的不等于,不包含null -- null 用数字判断筛选不出来 select name from Customer where referee_id !2 OR referee_id IS NULL;...
高考志愿填报有哪些技巧和方法
一年一度高考季,又高考志愿填报的时侯了。高考志愿填报的时侯,需要考虑的因素比较多,有的同学觉是离家越远越好,要放飞自我,家长再也管不了我了。有的同学觉得专业比学校牌子重要,只要报个好专业࿰…...
codereview时通常需要关注哪些
在团队成员之间互相进行代码审查(codereview)时,通常可以从以下几个方面来确保代码的质量和可维护性: 代码结构和格式: 检查代码是否遵循了项目约定的编码规范和风格指南。确保代码具有良好的可读性,比如合…...
DSP28335模块配置模板系列——定时器中断配置模板
一、配置步骤: 1.使能定时器时钟 EALLOW;SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK 1; // CPU Timer 2EDIS; 2.设置定时器的中断向量 EALLOW;PieVectTable.TINT2 &TIM2_IRQn;EDIS;其中TIM2_IRQn时定时器中断服务程序的名称 ,将中断服务函数的地址…...
使用 Apache Commons Exec 自动化脚本执行实现 MySQL 数据库备份
😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...
【中间件系列】浅析redis是否适合做消息队列
文章目录 一、简单的list消息队列1.命令示例2.伪代码示例3.方案优劣 二、Pub/Sub发布订阅1.消息丢失2.消息堆积 三、相对成熟的Stream1.redis命令介绍2.多消费者组测试3.Stream会持久化吗?4.消息堆积如何解决? 总结 用redis也是比较久了,并且…...
Logisim音乐盒背后的数字电路:计数器、ROM与蜂鸣器如何奏出《终生误》
Logisim音乐盒背后的数字电路:计数器、ROM与蜂鸣器如何奏出《终生误》 当一段熟悉的旋律从蜂鸣器中流淌而出,很少有人会思考这背后隐藏的数字魔法。本文将带您拆解一个基于Logisim的音乐盒设计,揭示计数器如何像指挥家一样协调时序、ROM怎样扮…...
QT窗口特效实战:从透明到异形控件的全方位实现指南
1. 从零开始理解QT窗口特效 第一次接触QT窗口特效时,我被那些酷炫的透明和异形界面深深吸引。记得当时看到Mac OS X的Dock栏那种毛玻璃效果,就特别想在自己的QT应用中实现类似效果。经过多年实战,我发现QT实现这些特效其实比想象中简单得多。…...
四自由度车辆与简支梁桥车桥耦合振动的Matlab实现
车桥耦合振动程序 matlab编程 四自由度车辆与简支梁桥车桥耦合 可提取车体垂直及转动加速度响应以及车轮响应 在交通工程领域,车桥耦合振动的研究对于保障桥梁结构安全以及行车舒适性至关重要。今天咱们就来讲讲如何用Matlab实现四自由度车辆与简支梁桥的车桥耦合振…...
MoveIt 2 Launch文件进阶:如何用MoveItConfigsBuilder灵活切换规划器(OMPL vs. Pilz)
MoveIt 2规划器切换实战:用MoveItConfigsBuilder实现OMPL与Pilz工业规划器的动态选择 在工业机器人应用开发中,运动规划器的选择往往决定了任务执行的效率和质量。想象一下这样的场景:你的机械臂需要在杂乱环境中快速避障移动时,…...
手把手拆解:一个QKD系统中的‘诱骗态’光源硬件是怎么搭出来的?
手把手拆解:一个QKD系统中的‘诱骗态’光源硬件是怎么搭出来的? 量子密钥分发(QKD)技术近年来从实验室走向商业化应用,其中诱骗态光源的设计与实现成为工程落地的核心挑战之一。不同于理论论文中简化的模型,…...
three-tile: 一个为Three.js应用注入真实地形的开源LOD模型库
1. three-tile究竟是什么? 第一次看到three-tile这个名字,很多人会误以为它又是一个WebGIS框架。但实际使用后你会发现,这个开源库的定位非常独特——它本质上是一个专为Three.js设计的LOD地形模型库。所谓LOD(Level of Detail&am…...
攻克内核加载难题:OpenArk工具驱动加载失败的系统化解决策略
攻克内核加载难题:OpenArk工具驱动加载失败的系统化解决策略 【免费下载链接】OpenArk The Next Generation of Anti-Rookit(ARK) tool for Windows. 项目地址: https://gitcode.com/GitHub_Trending/op/OpenArk OpenArk作为新一代Windows反Rootkit工具&…...
MATLAB实战:用BEMD算法分解图像并提取特征(附完整代码)
MATLAB实战:二维经验模态分解(BEMD)在图像特征提取中的创新应用 当我们需要从一张X光片中识别微小病灶,或是从卫星图像中提取城市道路网络时,传统图像处理方法往往力不从心。二维经验模态分解(BEMD)就像给图像做"CT扫描"࿰…...
实战LangGraph构建智能客服系统:在快马平台实现工单自动分类与处理全流程
今天想和大家分享一个用LangGraph构建智能客服系统的实战经验。这个项目主要解决工单自动分类和处理的问题,整个过程在InsCode(快马)平台上完成,从开发到部署一气呵成。 项目背景与需求分析 传统客服系统需要人工处理大量工单,效率低下且容易…...
企业高效知识体系:8大核心特征+可落地搭建框架,告别知识散乱
对于企业而言,知识从来不是“文件堆”,而是能支撑业务、培养新人、规避风险的核心资产。很多企业陷入“文档满天飞、新人没人带、老员工离职带跑经验”的困境,本质是没有搭建起高效、完整的知识体系。今天就一次性讲透:一个能真正…...
