【C++之容器篇】造轮子:模拟实现vector类

news2024/9/29 1:20:34

目录

    • 前言
    • 一、项目结构
      • 1. vector的简介
      • 2. 项目结构
    • 二、vector的底层结构
    • 三、默认成员函数
      • 1. 构造函数
        • (1)无参构造函数
      • 2. 拷贝构造函数
      • 3. 析构函数
      • 4. 赋值运算符重载函数
    • 四、迭代器
      • 1. 普通对象的正向迭代器
      • 2. const 对象的正向迭代器
    • 五、容量接口
      • 1. size()
      • 2. capacity()
      • 3. reserve()
      • 4. resize()
    • 六、元素访问接口
      • 1. operator[](size_t pos)
        • (1)const T& operator[](size_t pos)
        • (2)const T& operator[](size_t pos) const
      • 2. at(size_t pos)
        • (1)T& at(size_t pos)
      • 3. front()
      • 4. back()
    • 七、修改接口
      • 1. push_back(const T& x)
      • 2. pop_back()
      • 3.iterator insert(iterator pos,T val = T()))

前言

vector本质就是一个支持顺序存储数据,并且容量支持修改得到顺序表。但是vector的底层结构实现相比于之前实现的string来说略有不同。string中的底层结构是通过一个指针数组和两个变量来标识数组中数据的变化。vector是通过三个迭代器来标识上述过程。

一、项目结构

1. vector的简介

在这里插入图片描述

2. 项目结构

这个项目有两个文件,一个是test.cpp文件,另一个是vector.h文件。test.cpp文件主要是用来测试实现的vector的代码逻辑。vector.h文件主要是模拟实现vector的代码逻辑。
在这里插入图片描述
在这里插入图片描述

二、vector的底层结构

  1. 效果图:
    在这里插入图片描述
    在这里插入图片描述

  2. 代码实现

namespace hjt
{
	// 实现vector
	template <class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

	private:
		iterator _start;// 指向存储的第一个有效数据
		iterator _finish;// 指向存储的最后一个有效数据的下一个位置
		iterator _endofstorage;// 指向能够存储的最后一个位置的下一个位置
	};
}

代码中是通过三个迭代器来实现底层的。

  • _start:指向存储的第一个有效数据
  • _finish:指向存储的最后一个有效数据的下一个位置
  • _endofstorage: 指向能够存储的最后一个位置的下一个位置
    其实这个实现方法和string中的实现方法其实差不多,相当于_start表示空间的起始地址,_finish表示有效数据的个数,_endofstorage表示vector的实际容量。

三、默认成员函数

1. 构造函数

在这里插入图片描述

(1)无参构造函数

  • 代码
	// 无参构造函数
		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{}
  • 练习:
int main()
{
	hjt::vector<int> v1;
	hjt::vector<char> v2;
	hjt::vector<double> v3;
	hjt::vector<string> v4;
	return 0;
}

分析:v1表示一个存储int类型的vector对象,v2表示一个存储char类型的vector对象,v3表示一个存储double类型的vector对象,v4表示一个存储string类型对象的vector对象。

2. 拷贝构造函数

3. 析构函数

4. 赋值运算符重载函数

四、迭代器

1. 普通对象的正向迭代器

在这里插入图片描述

  • 代码:
// 普通迭代器
		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}
  • 代码:使用

2. const 对象的正向迭代器

  • 代码:
// const迭代器
		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

五、容量接口

1. size()

  • 代码:
		size_t size() const
		{
			return _finish - _start;
		}

2. capacity()

  • 代码:
 		size_t capacity() const
		{
			return _endofstorage - _start;
		}

3. reserve()

  • 代码:
// 扩容
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * size());
					delete[]_start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

4. resize()

  • 测试代码:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	v.resize(100,6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	return 0;
}

运行结果:
在这里插入图片描述

  • 测试代码2:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	v.resize(3, 6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	return 0;
}

运行结果:
在这里插入图片描述

  • 测试代码3:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	v.reserve(60);
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	v.resize(50, 6);
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	return 0;
}

运行结果:
在这里插入图片描述

六、元素访问接口

1. operator[](size_t pos)

(1)const T& operator[](size_t pos)

  • 代码:
	T& operator[](size_t pos)
		{
			return _start[pos];
		}
  • 测试代码:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述

(2)const T& operator[](size_t pos) const

  • 代码:
	const T& operator[](size_t pos) const
		{
			return _start[pos];
		}
  • 测试代码:

2. at(size_t pos)

(1)T& at(size_t pos)

  • 代码:
		T& at(size_t pos)
		{
			return _start[pos];
		}
  • 测试代码:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v.at(i) << " ";
	}
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述

3. front()

  • 代码:
// front
		T& front() const
		{
			return *_start;
		}

4. back()

  • 代码:
// back()
		T& back() const
		{
			return *(_finish - 1);
		}

测试:

int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	cout << "front:" << v.front() << endl;
	cout << "back:" << v.back() << endl;
}

运行结果:
在这里插入图片描述

七、修改接口

1. push_back(const T& x)

  • 代码:
// 尾插
		void push_back(const T& x)
		{
			if (_finish == _endofstorage)
			{
				// 需要进行扩容
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			_finish++;
		}
  • 测试:
// 测试尾插
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	hjt::vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;

	cout << v.size() << endl;
	cout << v.capacity() << endl;

	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述

2. pop_back()

  • 代码:
// 尾删
		void pop_back()
		{
			assert(_finish > _start);
			_finish--;
		}
  • 测试代码:
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	hjt::vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;

	v.pop_back();
	v.pop_back();
	v.pop_back();

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;


	return 0;
}

运行结果:
在这里插入图片描述
没有数据继续删除:
在这里插入图片描述

3.iterator insert(iterator pos,T val = T()))

  • 代码:
// insert()
		iterator insert(iterator pos, T val = T())
		{
			assert(pos >= _start && pos <= _finish);
			if (_finish == _endofstorage)
			{
				// 扩容
				// 如果需要进行扩容,注意更新迭代器,否则会导致迭代器失效
				size_t n = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + n;
			}

			// 挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}

			// 插入数据
			*pos = val;
			_finish++;
			return pos;
		}
  • 测试代码1:头插+尾插
// 测试insert
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	v.insert(v.begin(), 10);
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	v.insert(v.end(), 10);
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}
  • 测试代码2:在偶数前插入66
// 在偶数前面插入66
int main()
{
	hjt::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	hjt::vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		if (*vit % 2 == 0)
		{
			vit = v.insert(vit, 66);
			vit++;
		}
		vit++;
	}

	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述

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

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

相关文章

分布式-分布式理论笔记

分布式系统的特点 分布式系统技术就是用来解决集中式架构的性能瓶颈问题&#xff0c;来适应快速发展的业务规模&#xff0c;是建立在网络之上的硬件或者软件系统&#xff0c;彼此之间通过消息等方式进行通信和协调。 特点 具有可扩展性&#xff0c;不出现单点故障、服务或者…

Hadoop之——WordCount案例与执行本地jar包

目录 一、WordCount代码 (一)WordCount简介 1.wordcount.txt (二)WordCount的java代码 1.WordCountMapper 2.WordCountReduce 3.WordCountDriver (三)IDEA运行结果 (四)Hadoop运行wordcount 1.在HDFS上新建一个文件目录 2.新建一个文件&#xff0c;并上传至该目录下…

商品秒杀接口压测及优化

目录一、生成测试用户二、jmeter压测三、秒杀接口优化1、优化第一步&#xff1a;解决超卖2、优化第二步&#xff1a;Redis重复抢购3、优化第三步&#xff1a;Redis预减库存①商品初始化②预减库存一、生成测试用户 将UserUtils工具类导入到zmall-user模块中&#xff0c;运行生…

【STM32】【HAL库】遥控关灯1主机

相关连接 【STM32】【HAL库】遥控关灯0 概述 【STM32】【HAL库】遥控关灯1主机 【STM32】【HAL库】遥控关灯2 分机 【STM32】【HAL库】遥控关灯3 遥控器 需求 主机需要以下功能: 接收来自物联网平台的命令发送RF433信号给从机接收RF433信号和红外信号驱动舵机动作 方案设计…

【计算机网络期末复习】第二章 物理层

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为想复习学校计算机网络课程的同学提供重点大纲&#xff0c;帮助大家渡过期末考~ &#x1f4da;专栏地址&#xff1a; ❤️如果有收获的话&#xff0c;欢迎点…

Verilog语法之数学函数

Verilog-2005支持一些简单的数学函数&#xff0c;其参数的数据类型只能是integer和real型。 Integer型数学函数 $clog2是一个以2为底的对数函数&#xff0c;其结果向上取整&#xff0c;返回值典型的格式&#xff1a; integer result; result $clog2(n); 最典型的应用就是通过…

数据库(三):行锁和表锁,共享锁和排他锁,数据库引擎MyISAM和InnoDB,乐观锁和悲观锁

文章目录前言零、数据库引擎一、封锁粒度二、行锁三、表锁四、数据库中的属性锁4.2. 意向锁五、乐观锁和悲观锁总结前言 之前我们提到了数据库的隔离性可能会出现的若干问题&#xff0c;以及数据库为了解决这些问题而提出来的若干种隔离级别。实际上&#xff0c;数据库底层实现…

代码随想录算法训练营第二十七天|● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串

39. 组合总和 看完题后的思路 本题本质上还是一个传统排列题&#xff0c;不同之处在于每个元素可以重复选取。void f&#xff08;【】&#xff0c;startIndex&#xff0c;sum&#xff09;递归终止 if&#xff08;和target&#xff09;{ 加入&#xff1b; 返回&#xff1b; }递…

HTTPS为什么就安全了?我们做了什么?

目录 一 安全概念 二 HTTPS的安全措施 三 总结 一 安全概念 网络安全是一个比较笼统的概念。我们说网络安全的时候&#xff0c;往往会包含很多安全问题&#xff0c;包括网络设备层面、通信过程、数据本身等多方面引入的安全问题。比如设备被有意无意的破坏&#xff0c;链路…

微搭低代码从入门到精通-03 创建模型应用

我们在进行低代码开发的时候&#xff0c;第一个需要建立的概念就是应用。不管你开发的是小程序还是管理系统&#xff0c;最终的承载物就是应用。 而我们创建应用是一共可以创建两种类型的应用&#xff0c;自定义应用和模型应用。自定义应用对应着一页多端&#xff0c;你开发一…

【Hello Linux】 Linux的权限以及Shell原理

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍Linux的基础命令 Linux的权限以及Shell原理Shell的运行原理权限Linux中权限的概念如何切换用户如何提升当前操作的权限如何添加信任…

【C++:STL之栈和队列 | 模拟实现 | 优先级队列 】

目录 1. stack的介绍和使用 1.1 stack的介绍 1.2 stack的使用 2 栈的模拟实现 3 queue的介绍和使用 3.1 queue的介绍 3.2 queue的使用 4 queue的模拟实现 5 deque的介绍 5.1deque的原理介绍 5.2 deque的缺陷 5.3 为什么选择deque作为stack和queue的底层默认容器 6 p…

nodejs+vue+elementui在线求助系统vscode

目 录 摘 要 1 前 言 3 第1章 概述 4 1.1 研究背景 4 1.2 研究目的 4 1.3 研究内容 4 第二章 开发技术介绍 5 前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进…

加载sklearn covtype数据集出错 fetch_covtype() HTTPError: HTTP Error 403: Forbidden解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

微搭低代码从入门到精通07-基础布局组件

低码开发不同于传统开发&#xff0c;传统开发我们通常需要编写前端代码和后端代码。前端代码由HTML、CSS和JavaScript组成&#xff0c;后端代码我们通常要用后端语言比如Java来编写接口。 低码开发的特点是可视化开发&#xff0c;在编辑器中通过组件的拖拽来完成页面的编制。如…

莽村李青都看得懂的Vue响应式原理

Vue响应式原理八股文序违背老祖宗的决定将Vue响应式原理公众于世响应式数据&#xff08;Observe篇&#xff09;dom更新&#xff08;Wacther篇&#xff09;依赖收集八股文序 开篇来一段大家都会背诵的八股文。 某面试官&#xff1a; 请你简要介绍一下Vue的响应式原理。 答&am…

leaflet 读取上传的wkt文件,转换为geojson文件(示例代码056)

第056个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中上传WKT文件,解析wtk文件并转换为geojson,并在地图上显示图片。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式本示例所用的a.wkt示例源代码(共139行)…

AirServer在哪下载?如何免费使用教程

苹果手机投屏到电脑mac是怎么弄&#xff1f;你知道多少&#xff1f;相信大家对苹果手机投屏到电脑mac能在电脑上操作不是很了解&#xff0c;下面就让coco玛奇朵带大家一起了解一下教程。AIrServer是一款ios投屏到mac的专用软件&#xff0c;可将iOS上的音频&#xff0c;视频&…

make的使用及Makefile万能模板

make的使用及Makefile万能模板前言为什么用makemake的使用Makefile万能模板前言 gcc 的编译&#xff0c;是将源码生成可执行程序。 例如&#xff1a; gcc hello.c -o hello源码到可执行程序需要四步处理 硬件——》机器语言——》汇编语言——》 高级语言 1&#xff09;预处理…

【openGauss实战8】Schema的图文解读

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…