C++第二十一弹---vector深度剖析及模拟实现(上)

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、基本结构

2、默认成员函数

2.1、构造函数

2.2、析构函数 

2.3、拷贝构造函数 

2.3、赋值操作符重载

3、数据访问

4、迭代器获取

总结


1、基本结构

首先定义一个vector模版类,其中三个成员变量均为迭代器,且此处vector的迭代器是一个原生指针,我们这里为其定义别名iterator。

namespace lin 
{template<class T>//此处为类模板,实现不同数据类型的存储class vector{public://vector迭代器为原生指针typedef T* iterator;//定义指针类型的别名iteratortypedef const T* const_iterator;//...函数接口的实现private:iterator _start;// 指向容器的开始iterator _finish;// 指向容器中最后一个有效数据的下一个位置iterator _endofstorage;  // 指向存储容量的结尾};
}

私有成员变量:

_start: 这是一个指针,指向容器的第一个元素。
_finish: 这个指针指向容器中最后一个有效数据的下一个位置。
_endofstorage: 这个指针指向分配给vector的内存块的末尾。这不是最后一个有效元素的位置,而是整个内存块的结束位置,在这之后可能会有额外的未初始化空间,预留以实现当vector增长时无需重新分配整个数组。

2、默认成员函数

2.1、构造函数

vector()

默认构造的函数功能是构造一个没有元素的空容器。

默认构造函数实现有两种方式,第一种是直接通过初始化列表直接初始值,第二种是通过成员变量的缺省值

1.初始化列表

//将成员变量都初始化为空
vector(): _start(nullptr), _finish(nullptr), _endofstorage(nullptr)
{}

2. 缺省值

//会默认使用缺省值构造
vector()
{}private:iterator _start=nullptr;		iterator _finish=nullptr;		iterator _endofstorage=nullptr;  
};

 vector(size_t n, const T& val = T()) 

填充构造函数功能是构造一个包含 n 个元素的容器。每个元素都是 val 值。

思想:

为了确保空间足够,我们可以先将空间扩容至n(减少扩容消耗)再将n个值尾插到容器中

//构造n个数值 并初始化为val
vector(size_t n, const T& val = T())
{reserve(n);//细节,先开空间for (size_t i = 0; i < n; i++){push_back(val);}
}

注意:

vector构造函数中的const T& val = T()T是一种类型,T的类型取决于vector后的<>,<>中是什么类型,T就是什么类型。

T是内置类型时,T() == 0。

char()需要强转成int才能看到0,因为ASCII码值为0的char字符是'\0',屏幕上显示不出来。

当T是自定义类型时,T()调用无参或者全缺省构造函数构造一个匿名对象,若T类中不存在无参全缺省构造方法时报错。

  vector(InputIterator first, InputIterator last)

迭代器区间构造函数功能是将[first,last)区间的元素构造成一个新容器,注意 last位置的元素是不取的。

  1. template <class InputIterator> 是一个函数模板函数参数是一个迭代器类型
  2. 函数实现原理:从 first 位置开始遍历迭代器区间,遍历的同时将该位置的数据尾插到vector上,直到遍历到 last 位置则结束循环
//类模板里面有函数模板
//template<typename InputIterator>
template <class InputIterator>//与类模板类型名区分
vector(InputIterator first, InputIterator last)//拷贝迭代器区间
{while (first != last)//起始与结尾不相等则插入{push_back(*first);++first;//向后移动}
}

 如果实现了迭代器区间构造函数以及填充构造函数之后,去实例化vector<int> v(10,1)则会出错,因为此时的参数都为int类型,而填充构造函数 vector(size_t n, const T& val = T()) 的第一个类型时无符号整数,迭代器区间构造函数  vector(InputIterator first, InputIterator last)是两个相同类型的模板参数,此时会优先调用更匹配的迭代器区间构造函数,然后10-1不是一个区间,也不能解引用,因此编译器报错。

解决办法是重载一个填充构造函数,如下:

  vector(int n, const T& val = T())

//构造n个数值 并初始化为val
vector(int n, const T& val = T())//x64有问题
{reserve(n);//细节,先开空间for (int i = 0; i < n; i++){push_back(val);}
}

2.2、析构函数 

析构函数功能是销毁动态开辟的空间。

释放空间并将指针置空即可。

~vector()
{delete[] _start;_start = _finish = _endofstorage = nullptr;
}

2.3、拷贝构造函数 

vector(const vector<T>& v)

函数功能构造一个包含 v 中所有元素的容器。

先开辟一个与原容器大小相等的空间,然后直接尾插即可。

//v(v1)
vector(const vector<T>& v)
{reserve(v.capacity());//开始扩容,减少频繁扩容for (auto& x : v)//字符串可能有问题,加&{push_back(x);//尾插数据}
}

 注意:reserve()与push_back()函数在后面有实现!!!

vector(initializer_list<T> il) 

initializer_list 是一个类,支持{}初始化。 

实现思想是使用范围for遍历该类,遍历的同时尾插数据即可,为了减少扩容消耗,可以提前开辟好空间。 

//vector<int> v ={1,2,3,4,5}
vector(initializer_list<T> il)
{reserve(il.size());//提前开好il大小的空间for (auto& x : il){push_back(x);//尾插}
}

2.3、赋值操作符重载

 vector<T>& operator=(vector<T> v)

赋值操作符重载的功能是将新内容分配给容器,替换其当前内容,并相应地修改其大小。

此处为现代写法,直接交换两个容器,函数参数不能加引用。

void swap(vector<T>& v)
{swap(_start, v._start);//调用库函数的swap函数swap(_finish, v._finish);swap(_endofstorage, v._endofstorage);
}
vector<T>& operator=(vector<T> v)
{swap(v);//调用就近类内函数return *this;
}

3、数据访问

operator[](size_t pos)

使用下标加 [ ] 访问数据。

T& operator[](size_t pos)//[]运算符重载
{assert(pos < size());return _start[pos];
}
const T& operator[](size_t pos) const
{assert(pos < size());return _start[pos];
}

 front()

获取第一个元素(即_start指向的位置)。

T& front()
{return *_start;
}const T& front()const
{return *_start;
}

 back()

获取最后一个元素(_finish前面一个位置)。

T& back()
{return *(_finish - 1);
}const T& back()const
{return *(_finish - 1);
}

4、迭代器获取

begin()

返回容器的首地址(_start)。

iterator begin()
{return _start;
}
const_iterator begin() const //无允许修改,加const修饰函数
{return _start;
}

end()

返回容器当中有效数据的下一个数据的地址(_finish)。

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

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

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

相关文章

数字经济与资本市场的密切关系!

数字经济的崛起&#xff0c;如同一股强劲的东风&#xff0c;吹拂着经济社会的每一个角落&#xff01;它带来了“新领域”和“新赛道”&#xff0c;赋予了“新动能”和“新优势”&#xff0c;成为引领中国经济增长和社会发展的重要力量。如今&#xff0c;发展数字经济已上升为国…

人人都是产品经理,尼恩产品经理面试宝典(史上最全、定期更新)

《人人都是产品经理&#xff0c;尼恩产品经理面试宝典》&#xff08;史上最全、定期更新&#xff09; 本文版本说明&#xff1a;V1 IT不老新物种 的定义 大龄男IT &#xff1a;APM 架构经理 项目经理 高级开发&#xff0c;没有中年危机 大龄女IT&#xff1a;DPM 产品经理 …

为什么宋以前权臣篡位多、宋以后权臣篡位少?

时代不同&#xff0c;主要问题也不同。天下的大气候&#xff0c;自然就要左右王朝的小气候。权臣篡位&#xff0c;得先有权臣。但是&#xff0c;如果当权臣都没有了&#xff0c;又怎么可能有权臣篡位呢&#xff1f;这是一个社会基础的变化。宋以后的主要矛盾是中原和草原的争锋…

springboot+vue+mybatis jsp二手商城系统+PPT+论文+讲解+售后

随着互联网发展对各个领域的影响&#xff0c;互联网为人们的生活和工作带来了翻天覆地的变化。为了提升学校在校学生学籍管理方面的工作效率&#xff0c;实现学校在信息化方面的发展&#xff0c;提出了学校学籍管理系统。论文首先介绍了学校学生学籍管理系统的研究背景&#xf…

Mongodb 可视化工具Robot 3t安装【windows环境下】

下载应用 打开连接点我 选择windows版本并点击下载 下载完毕&#xff0c;双击并傻瓜安装 连接数据库 点击图标&#xff0c; 点击create创建连接 填写host和port 如果有用户名密码的&#xff0c;在authentication里填写 5. save 并连接即可使用&#xff01;

【深入学习Redis丨第一篇】Redis服务器部署详解

前言 小伙伴们大家好&#xff0c;我是陈橘又青&#xff0c;今天起 《深入学习Redis》 专栏开始更新。本专栏将专为希望深入了解Redis的开发者、系统架构师以及数据库爱好者而写的免费专栏。从Redis的基本概念入手&#xff0c;逐步深入到其内部实现和高级用法。希望能帮助你更好…

[ARM-2D 专题] 1.开始:基本工程搭建,编译和开发环境配置问题解决

要开始使用ARM-2D&#xff0c;前期两个准备工作需要完成&#xff1a; 一块mcu内核为cortex-M的板子&#xff0c;带显示屏&#xff08;彩色TFT屏&#xff0c;分辨率建议320x240或以上&#xff0c;带TP更佳&#xff09;。基于这个板子可以正常运行的keil MDK的工程。 好了&#…

手写promise、call、apply、debounce、throttle 等

1、promise 1.1 实现resolve和reject class MyPromise {// 构造方法constructor(executor) {// 初始化值this.initValue()// 初始化this指向this.initBind()try {// 执行传进来的函数executor(this.resolve, this.reject)} catch (e) {// 捕捉到错误直接执行rejectthis.rejec…

高铁Wifi是如何接入的?

使用PC端的朋友&#xff0c;请将页面缩小到最小比例&#xff0c;阅读最佳&#xff01; 在飞驰的高铁上&#xff0c;除了窗外一闪而过的风景&#xff0c;你是否好奇过&#xff0c;高铁Wifi信号如何连接的呢&#xff1f; 远动的火车可不能连接光纤吧&#xff0c;难道是连接的卫星…

CSS Canvas鼠标点击特效之天女散花(文本粒子动画)

1.效果 2.代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;padding: 0;w…

工控一体机10.1寸显示器电容触摸屏(YA1308101JK)产品规格说明书

如果您对工控一体机有任何疑问或需求&#xff0c;或者对如何集成工控一体机到您的业务感兴趣&#xff0c;可移步控芯捷科技。 一、硬件功能介绍 YA1308101JK产品介绍&#xff1a; YA1308101JK搭载 Android10 主流操作系统&#xff0c;具有系统版本更高、占用内存更低、运行效率…

【领导力SE模型影响地图】如何分辨一个管理者有没有好的领导力? ​

影响地图是以思维导图的形式&#xff0c;在业务目标和交付物之间建立起强关联。 影响地图分为四个层级&#xff1a; 第1层级&#xff1a;目标&#xff08;Why&#xff09;- 想要达成的业务目标。 第2层级&#xff1a;利益相关者&#xff08;Who&#xff09;- 谁能够帮助达成…

新能源汽车推行精益生产:绿色动力下的效率革命

在新能源汽车行业迅猛发展的当下&#xff0c;推行精益生产已成为提升竞争力的关键所在。精益生产&#xff0c;作为一种以客户需求为导向、追求流程最优化和浪费最小化的管理理念&#xff0c;正逐步在新能源汽车领域展现出其独特的魅力。 新能源汽车的兴起&#xff0c;不仅代表了…

如何本地 Debug React 源码

日常开发过程中&#xff0c;有时 debug react 源代码进行问题排查。一种方案是直接把通过 html 引入进来&#xff0c;另外一种是编译并通过 yarn 链接到项目中&#xff0c;本地将介绍如何通过这两种方法进行代码 Debug。 页面引入源代码方式 这种方式比较简单&#xff0c;直接…

眼精星和金鸣识别新增智能结构化识别,助您快速筛选和统计数据

熟悉眼精星票证识别系统或金鸣表格文字识别大师的用户都知道&#xff0c;近日&#xff0c;这二款软件同时上线了“智能结构化”功能&#xff0c;那么&#xff0c;什么是智能结构化呢&#xff1f; 准确地说&#xff0c;我们这里的智能结构化应为OCR智能结构化&#xff0c;因为它…

多家大模型公司被爆“卖身”,有创业者称接单能力很重要

百模大战下&#xff0c;行业开始“洗牌”。 据外媒《The Information》的报道&#xff0c;随着底层通用大模型格局的基本落成&#xff0c;投资者的热情正在转向支持人形机器人等其他技术。 与此同时&#xff0c;科技巨头和生成式AI的早期赢家也正在加速掀起一场新浪潮&#x…

Flink搭建

目录 一、standalone模式 二、Flink on Yarn模式 一、standalone模式 解压安装Flink [rootbigdata1 software]# tar -zxvf flink-1.14.0-bin-scala_2.12.tgz -C /opt/module/ [rootbigdata1 module]# mv flink-1.14.0/ flink-standalone 2.进入conf修改flink-conf.yaml job…

KaiwuDB 受邀出席中国智能化油气管道与智慧管网技术交流大会

导 读 5月22-24日&#xff0c;由中国石油学会石油储运专业委员会、石油工业标准化技术委员会油气储运专标委等联合主办的“第十三届中国智能化油气管道与智慧管网技术交流大会”在浙江省杭州市盛大召开&#xff0c;KaiwuDB 受邀亮相大会。浪潮院士、山东浪潮数据库技术有限公司…

二区5分纯生信|单细胞+非负矩阵+AlphaFold+机器学习组合

说在前面 学文不看刊 这篇分析总体来说工作量不算大&#xff0c;scRNA联合bulkRNA分析&#xff0c;多种机器学习组合预测模型&#xff0c;最后用了AlphaFold2预测蛋白及AutoDock分子对接 非常适合小白学习和模仿&#xff0c;其次在筛选出核心基因后可以再加几个外部数据集观…

勒索软件统计数据揭示了网络勒索的惊人速度

本文通过各种报告摘录&#xff0c;提供了有关当前勒索软件形势的统计数据和见解。 全球勒索病毒危机加剧 NTT安全控股《2024全球威胁情报报告》&#xff08;2024年5月&#xff09; 据NTT安全控股公司的《2024年全球威胁情报报告》显示&#xff0c;勒索软件和勒索事件在2023年激…