vector容器模拟实现(上)

news2024/11/18 19:46:55

1.1:模板设置

因为不能与库已经有的vector冲突,首先定义命名空间namespace my

image-20221211201643870

使用类模板。

1.2:成员变量

image-20221211202033533

vector有size,capacity,同时也要进行扩容操作和缩容(shrink to fit)操作,所以需要3个迭代器。

	private:
		iterator _start;
		iterator _end;//最后一个数据的下一个位置
		iterator _endofstorage;

1.3:迭代器

image-20221211201134037

在c++官网中,迭代器有const和非const,一般来说只读的,设计const接口,只写的设计非const,可读可写提供2个。

		typedef T* iterator;
		typedef const T* _iterator;
		iterator begin()
		{
			return _start;
		}
		_iterator begin()const
		{
			return _start;
		}
		iterator end()
		{
			return _end;
		}
		_iterator end()
		{
			return _end;
		}

1.4:[]重载

c++中很多有关赋值的操作符都会涉及到传引用返回

2个原因如下:

  • 传引用可避免拷贝,提升效率
  • 对于连续赋值,a=b=c,c++中赋值操作符返回的是左值(操作符左边的数,不是它的值)的引用。如果不用传引用返回,在c语言中我们学了函数的返回值是一个临时变量,具有const属性,这里也一样,a=b首先返回a的一个临时拷贝对象,再把c的值赋给这个临时对象。

同时,在库中,也给了const和非const版本。

且对于越界检查,库采用的是assert检查方式

image-20221211202939955

		T& operator[](size_t pos)
		{
			//c++里面有断言检查是否越界
			assert(pos < size);
			return _start[pos];
		}
		const T& operator[](size_t pos)const
		{
			assert(pos < size());
			return _start[pos];
		}

1.5:构造函数

		vector()
			:_start(nullptr)
			,_end(nullptr)
			,_endofstorage(nullptr)
		{}

构造函数先用初始化列表全给空指针,后续再完善。

1.6:size()接口

	size_t size()const
	{
		return _end - _start;
	}

1.7:capacity()接口

		size_t capacity()const
		{
			return _endofstorage - _start;
		}

1.8:reserve接口

功能:设置空间,预留空间。

	void reserve(size_t n)
	{
		if (n > capacity())
		{
			size_t oldsize = size();
			//需要扩容
			T* temp = new T[n];
			//使用new可以调用默认构造,比malloc要舒服的多。
			//要注意如果start为空的时候,拷贝不了任何东西所以先判断start
			if (_start)
			{
				memcpy(temp, _start, sizeof(T) * oldsize);
				delete[] _start;
		    }
			_start = temp;
			_end = _start + oldsize;
			_endofstorage = _start + n;
		}
	}

当需要预留的大小大于本身的容量(这里使用接口获取容量),就需要扩容。扩容的时候开辟新空间,将原来的start位置开始的数据,T类型大小*size大小的空间拷贝给新空间,释放掉旧空间。然后再将新空间(因为是数组,数组名是首元素地址)赋值给start,end加上原来的大小+start,这里我使用了oldsize,是因为如果不记录旧的大小,当start被新空间赋值的时候,size就会用新的start-旧的end,明显不可能,因此首先用oldsize记录原来的size。

1.9:resize()接口

使用方式:resize(n,val)

三种情况:

  • n>capacity()
  • size()<n<=capacity()
  • n<size()
		//这里使用匿名对象,并使用缺省值,缺省值是使用的默认构造函数
		void resize(size_t n, T val = T())
		{
			//1:n>capacity
			if (n > capacity())
			{
				//开始扩容
				reserve(n);
			}
			//2:size<n<=capacity无需扩容填充数据即可
			else if (size() < n <= capacity())
			{
				while (_end < _start + n)
				{
					*end = val;
					++end;
				}
			}
			//3:n<size
			else
			{
				_end = _start + n;
			}
		}

image-20221211204847481

官网说val的类型就是模板的参数类型,也就是T,当不给出val值的时候,就会调用T的默认构造函数,所以我们有时候给出默认构造函数是有意义的。同时这里的T也是一个缺省值。

1.10:pushback接口

功能:插入数据

		void pushback(const T& x)
		{
			//要检查扩容
			//当end指针等于容量指针
			if (_end == _endofstorage)
			{
				//此时需要扩容
				size_t newcapacity = capacity() = 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}
			*end = x;
			++end;
		}

当我们需要插入的时候就得检查扩容,这在学习链表和顺序表的时候也有。

1.11:empty()接口

		bool empty()
		{
			return _start == _end;
		}

1.12:popback接口

		void popback()
		{
			assert(!empty());
			--_end;
		}

1.13:insert接口

功能:在pos位置插入val

	void insert(iterator pos, const T& val)
	{
		assert(pos < _end);
		assert(pos >= _start);
		if (_end == _endofstorage)
		{
			size_t len = pos - _start;
			int newcapacity = capacity() > 0 ? 4 : capacity() * 2;
			reserve(newcapacity);
			pos = _start + len;
		}
		iterator _finish = _end - 1;
		while (_finish >= pos)
		{
			*(_finish + 1) = *_finish;
			--_finish;
		}
		*pos = val;
		++_end;
	}

还是需要检查扩容,这里为什么要保存pos和start的差值呢,如果扩容是用的reserve是异地扩容,那pos位置就迭代器失效了,因此需要保存差值。

插入数据,数据右移,所以需要把某位置的数据给+1的位置,如果我们直接使用end迭代的话,end是末尾元素下一个位置,所以需要用他前面一个位置作为迭代器,迭代到=pos位置,然后再让pos迭代器内容指向val。

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

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

相关文章

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java杨柳农贸市场摊位管理系统qr3ri

大四计算机专业的同学们即将面临大学4年的最后一次考验--毕业设计。通过完成毕业设计来对过去4年的大学学习生活做一个总结&#xff0c;也是检验我们学习成果的一种方式&#xff0c;毕业设计作品也是我们将来面试找工作的一个敲门砖。 选题前先看看自己掌握哪些技术点、擅长哪…

mysql首次安装error 1045 28000解决

mysql首次安装error 1045 28000解决 首先找到了这个教程&#xff0c;按其操作一步一步来&#xff0c;发现到登录输入密码这一步&#xff0c;怎么样都报错 2021MySql-8.0.26安装详细教程&#xff08;保姆级&#xff09; 然后按照这篇操作&#xff0c;但还是不行 MySQL安装1045错…

[附源码]Python计算机毕业设计Djangoospringboot作业管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

通过窗口看世界之 界面制作如此简单-带你制作旅游观光系统界面-----效果图展示

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 玩归玩闹归闹&#xff0c;别拿java开玩笑 ⭐旅游管理系统部分效果图展示⭐ 文章目录⭐旅游管理系统部分效果图…

持久化的配置都不知道,也敢说精通Redis?

前言 所谓持久化可以简单理解为将内存中的数据保存到硬盘上存储的过程。持久化之后的数据在系统重启或者宕机之后依然可以进行访问&#xff0c;保证了数据的安全性。一键获取最先java文档。 Redis有两种持久化方案&#xff0c;一种是快照方式&#xff08;SNAPSHOTTING&#xff…

前端 | 前端设计设计及代码收集

全部来源于Github,侵权删&#xff01; 1.Maxime Euzire 2.Shubham Singh | Resume 3.Natasha Theodora Petrus 4.Ana Mara Martnez Gmez 5.bagussona.github.io 6.leodevbro.github.io 7.yuanlinping.github.io 8.Dr.Q 9.sureshmurali.github.io 10.Chandrika Deb | Software…

常见的接口测试面试题

1、按你的理解&#xff0c;软件接口是什么&#xff1f; 答&#xff1a; 就是指程序中具体负责在不同模块之间传输或接受数据的并做处理的类或者函数。 2、HTTP和HTTPS协议区别&#xff1f; 答&#xff1a; https协议需要到CA&#xff08;Certificate Authority&#xff0c;证…

[附源码]JAVA毕业设计医疗器械销售电子商城(系统+LW)

[附源码]JAVA毕业设计医疗器械销售电子商城&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

Spring:Ioc

目录 一、Spring的两大核心机制 1、IOC/ DI:控制反转和依赖注入 2、AOP:面向切面编程 二、IOC/ DI:控制反转 / 依赖注入&#xff1a; 1、bean的基础配置&#xff1a; 2、bean的实例化 3、配置bean 4、依赖注入方式 三、注解开发定义bean 注解依赖注入 Spring设计理念 …

Spring推断构造方法源码深度解析

文章目录前言思考目标一、bean的实例化入口-createBeanInstance1、源码逻辑思路**核心点&#xff0c;主要做了几件事情**2、instantiateBean-默认无参实例化3、instantiate-实例化4、instantiateClass-实例化类二、获取构造函数候选数组-determineConstructorsFromBeanPostProc…

这十套练习,教你如何用Pandas做数据分析(04)

练习4-Apply函数 探索1960 - 2014 美国犯罪数据 步骤1 导入必要的库 运行以下代码 import numpy as np import pandas as pd 步骤2 从以下地址导入数据集 运行以下代码 path4 ‘…/input/pandas_exercise/pandas_exercise/exercise_data/US_Crime_Rates_1960_2014.csv’…

微信小程序|入门进阶

接下来点击新建项目就可以在主界面中预览到我们的豆瓣电影示例了 小程序开发初体验 Hello world 希望是一个从零到一的转换过程~ 创建项目 接下来创建一个新的项目,理解小程序项目的基本结构和一些基础语法。 官方的开发工具为此准备了一个QuickStart项目。在创建过程中,…

利用jrebel与arthas在centos7 springboot热部署

jrebel 热部署 jrebel在本地是可以class xml一起热部署&#xff0c;但是远程热部署xml不行&#xff0c;所以用arthas代替去热部署xml 1.jrebel 反向代理 因为jrebel是收费插件&#xff0c;所以要高一些小动作咱们才能‘正常’使用&#xff0c;当然你也可以拿别人代理好的操作…

并发基础(五):ThreadPoolExecutor源码解析

尺有所短&#xff0c;寸有所长&#xff1b;不忘初心&#xff0c;方得始终。 请关注公众号&#xff1a;星河之码 在JDK提供的几种线程池技术&#xff0c;除了JDK8新加的newWorkStealingPool之外&#xff0c;其余的几种线程池都是通过ThreadPoolExecutor 来实现线程池技术&#x…

本周大新闻|FDA公布XR认证医疗名单,索尼推数字孪生平台Mapray

本周大新闻&#xff0c;AR方面&#xff0c;苹果首款MR头显或推迟至2023年下半年发布&#xff1b;FDA官网公布经过认真的AR/VR医疗方案名单&#xff1b;索尼预测AR/VR光学发展路径&#xff1b;索尼公布3D数字孪生平台Mapray&#xff1b;索尼公布ToF AR SDK。 VR方面&#xff0c…

Docker简介与安装

一、Docker 简介 1.1 为什么选择Docker? 更高效的利用系统资源更快速的启动时间一致的运行环境持续交付和部署更轻松的迁移更轻松的维护和扩展 1.2 Docker组件 1.2.1 Docker服务器与客户端 Docker是一个客户端-服务器&#xff08;cs&#xff09;架构程序。Docker客户端只…

linux下共享内存和消息队列实现多进程间数据收发

linux下进程通信的方式有很多&#xff0c;共享内存&#xff0c;消息队列&#xff0c;管道等。共享内存可以传输大量数据&#xff0c;但是多个进程同时读取共享内存就会出现脏读&#xff0c;可以借助消息队列实现多进程消息发送和接收。这种组合方式在实际开发中应用还是很多的&…

计算机网络复习(五)

考点&#xff1a;UDP 拥塞控制 TCP三次握手四次握手 P247 熟知端口号 P215 TCP报文计算5-36.假定TCP采用一种仅使用线性增大和乘法减小的简单拥塞控制算法&#xff0c;而不使用慢开始。发送窗口不采用字节为计算单位&#xff0c;而是使用分组pkt为计算单位。在一开始发送窗口为…

时序预测 | MATLAB实现VAR和GARCH时间序列预测

时序预测 | MATLAB实现VAR和GARCH时间序列预测 目录 时序预测 | MATLAB实现VAR和GARCH时间序列预测预测效果基本介绍程序设计VARGARCH参考资料预测效果 基本介绍 机器学习可其用于时间序列问题的分类和预测。在探索时间序列的机器学习方法之前,尝试统计时间序列预测方法,它列…

SQL开窗函数之percent_rank、first_value、nth的用法

开窗函数 当我们需要进行一些比较复杂的子查询时&#xff0c;聚合函数就会非常的麻烦&#xff0c;因此可以使用开窗函数进行分组再运用函数查询。窗口函数既可以显示聚集前的数据&#xff0c;也可以显示聚集后的数据&#xff0c;可以在同一行中返回基础行的列值和聚合后的结果…