【C++初阶】vector的模拟实现

news2024/11/24 9:44:23

文章目录

  • vector的介绍
  • vector的模拟实现
    • 成员变量
    • Member functions
      • constructor(构造函数)
      • destructor(析构函数)
      • operator=
    • Iterators
      • begin
      • end
    • Capacity
      • size
      • capacity
      • reserve
      • resize
    • Element access
      • operator[]
    • Modifiers
      • push_back
      • pop_back
      • insert
      • erase
      • swap
  • 完整版实现代码
    • vector.h
    • test.cpp

vector的介绍

vector是C++ STL库中一个重要的容器,它分为以下几个部分(我们也将在vs2022编译环境下实现以下几个部分)
Member functions
在这里插入图片描述
Iterators
在这里插入图片描述
Capacity
在这里插入图片描述
Element access
在这里插入图片描述
Modifiers
在这里插入图片描述
Allocator
在这里插入图片描述
Non-member function overloads
在这里插入图片描述
Template specializations
在这里插入图片描述

vector的模拟实现

接下来我们要模拟实现每个部分中最重要也是最常见的几个接口(其中的Allocator、Non-member function overloads、Template specializations这三部分因为涉及到有的知识还未学到,或者不常用的情况所以没有实现)
vector被实现位类模板

成员变量

在这里插入图片描述
从这里可以看出迭代器是T类型指针
在这里插入图片描述
在这里插入图片描述

Member functions

constructor(构造函数)

在这里插入图片描述
其中每个构造函数中的形参alloc是向内存池申请空间,是编译器为了方便管理自己实现了一个内存池,而我们并不用考虑这些,所以不用管,有兴趣的可以去了解一下。
在这里插入图片描述
在这里插入图片描述

destructor(析构函数)

在这里插入图片描述
在这里插入图片描述
这里如果delete的是空指针也是合法的

operator=

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Iterators

begin

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

end

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里的begin和end分为普通迭代器和const修饰的迭代器,普通迭代器返回值可读可写,const修饰的迭代器返回值只可读不可写

Capacity

size

在这里插入图片描述
在这里插入图片描述

capacity

在这里插入图片描述
在这里插入图片描述

reserve

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

resize

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Element access

operator[]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
还有front和back但是有了operator[]实现的意义不大,所以没有实现

Modifiers

push_back

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pop_back

在这里插入图片描述
在这里插入图片描述

insert

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

erase

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

swap

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整版实现代码

vector.h

#pragma once
namespace lzf
{
	template < class T >
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		void swap(vector<T>& v)
		{
			swap(_start, v._start);
			swap(_finish, v._finish);
			swap(_endofstorage, v._endofstorage);
		}
		//构造一个空类
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}
		//拷贝构造
		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			/*iterator temp = new T[v.size()];
			memcpy(temp, v._start, sizeof(T) * v.size());
			_start = temp;
			_finish = _start + v.size();
			_endofstorage = _start + v.capacity();*/
			vector temp(v);
			swap(temp);
		}
		//类模板
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			/*size_t sz = last - first;
			iterator temp = new T[sz];
			memcpy(temp, first, sizeof(T) * sz);
			_start = temp;
			_finish = _start + sz;
			_endofstorage = _start + sz;*/
			while (first != last)
			{
				push_back(*first);
				++first;
			}

		}
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
		}
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin()const
		{
			return _start;
		}
		const_iterator end()const
		{
			return _finish;
		}
		size_t size()const
		{
			return _finish - _start;
		}
		size_t capacity()const
		{
			return _endofstorage - _start;
		}
		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 reserve(size_t n)
		{
			if (_start + n > _endofstorage)
			{
				size_t sz = size();
				iterator temp = new T[n];
				if (_start)
				{
					memcpy(temp, _start, sizeof(T) * sz);
					delete[] _start;
				}
				_start = temp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}
		void resize(size_t n, const T& val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				if (_start + n > _endofstorage)
				{
					size_t sz = size();
					iterator temp = new T[n];
					if (_start)
					{
						memcpy(temp, _start, sizeof(T) * sz);
						delete[] _start;
					}
					_start = temp;
					_finish = _start + sz;
					_endofstorage = _start + n;
				}
				while (_finish != _endofstorage)
				{
					*_finish = val;
					_finish++;
				}
			}
		}
		void push_back(const T& x)
		{
			if (_finish == _endofstorage)
			{
				//扩容
				size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
				/*size_t sz = size();
				iterator temp = new T[newcapacity];
				memcpy(temp, _start, sizeof(T) * sz);
				delete[] _start;
				_start = temp;
				_finish = _start + sz;
				_endofstorage = _start + newcapacity;*/
				reserve(newcapacity);
			}
			//插入数据
			*_finish = x;
			++_finish;
		}
		void pop_back()
		{
			assert(_finish > _start);
			--_finish;
		}
		iterator insert(iterator pos, const T& x)
		{
			//检测插入位置是否正常
			assert(pos <= _finish);
			assert(pos >= _start);
			if (_finish == _endofstorage)
			{
				//扩容
				size_t sz = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);
				pos = _start + sz;
			}
			//插入数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;
			return pos;
		}
		iterator erase(iterator pos)
		{
			//检测删除位置是否正常
			assert(pos < _finish);
			assert(pos >= _start);
			//插入数据
			iterator begin = pos;
			iterator end = _finish - 1;
			while (begin != end)
			{
				*begin = *(begin + 1);
				++begin;
			}
			_finish = begin;


			return pos;
			assert(pos >= _start);
			///*assert(pos < _finish);

			//iterator begin = pos + 1;
			//while (begin < _finish)
			//{
			//	*(begin - 1) = *begin;
			//	++begin;
			//}

			//--_finish;*/

			return pos

		}
	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};
	void test_vector1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		//cout << endl;
	}
	void test_vector2()
	{
		vector<int>v1;
		vector<int>v2;
		v1.reserve(100);
		cout << v1.capacity() << endl;
		v2.resize(100);
		cout << v2.capacity() << endl;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		//vector<int> v3(v1);
		vector<int> v3(v1.begin() + 1, v1.end() - 1);
		for (auto e : v3)
		{
			cout << e << " ";
		}
	}
	void test_vector3()
	{
		vector<int>v1;
		vector<int>v2;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		vector<int> v3(v1.begin() + 1, v1.end() - 1);
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;
		v3.insert(v3.begin(), 4);
		v3.insert(v3.end(), 4);
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int>::iterator pos = find(v3.begin(), v3.end(), 2);
		//vector<int>::iterator pos = find(v3.begin(), v3.end(), 4);
		cout << *pos;
		//v3.erase(pos);
		//vector<int>::iterator pos1 = find(v3.begin(), v3.end(), 4);
		//v3.erase(pos1);
		//for (auto e : v3)
		//{
		//	cout << e << " ";
		//}
		cout << endl;

		// 要求删除v1所有的偶数
		/*vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			if (*it % 2 == 0)
			{
				v1.erase(it);
			}

			++it;
		}*/
	}
	void test_vector4()
	{
		vector<int>v1;
		//vector<int>v2;
		v1.push_back(1);
		v1.push_back(2);
		//v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		// 要求删除v1所有的偶数
		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			if (*it % 2 == 0)
			{
				it = v1.erase(it);
			}
			else
			{
				++it;
			}

		}
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
		v1.pop_back();
		v1.pop_back();
		//v1.pop_back();
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

test.cpp

void test()
{
	int* p = nullptr;
	delete p;
}
int main()
{
	//lzf::test_vector1();
	//lzf::test_vector2();
	//test();
	//lzf::test_vector3();
	lzf::test_vector4();
	return 0;
}

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

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

相关文章

手办商城系统|Springboot+vue+ElementUI手办商城系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

C语言重点解剖预处理要点速记

1.宏定义字符串的时候一定要带上双引号。 2.程序的翻译&#xff0c;就是把文本代码翻译成二进制代码。分为4个阶段&#xff0c;即预处理&#xff0c;编译&#xff0c;汇编&#xff0c;链接。 3.预处理&#xff1a;头文件展开&#xff0c;去注释&#xff0c;宏替换&#xff0c…

基于Spring cloud + vue 的前后端分离的社团管理系统,数据库采用MYSQL,前端使用 VUE + element

背景 因学校没有成熟的社团管理系统&#xff0c;一为满足学校需求&#xff0c; 其次开源的社团管理项目&#xff0c;多为mvc ssm框架 很少有前后端分离的微服务框架&#xff0c;为了科技的发展&#xff0c; 更好学习解决高并发问题&#xff0c;也为了更好地掌握锤炼新技术&…

Web前端:广州蓝景实训

0基础也能学&#xff0c;5个月的课程时间&#xff0c;从小白到就业课程内容紧贴市场就业要求。广州蓝景前端实训课程&#xff0c;6年时间培养出过千名工程师&#xff0c;成功就业。今天就跟大家分享&#xff0c;蓝景学员的学习体验流程&#xff1a; 一、前端技术学习 1、授课…

3.Kafka

1.定义 1.1传统定义 Kafka是一个分布式的基于发布订阅模式的消息队列&#xff0c;主要应用于大数据的实时处理领域发布订阅&#xff1a;消息发布者不会直接将消息发送给订阅者&#xff0c;而是将发布的消息分为不同的类别&#xff0c;订阅者只接收感兴趣的消息 1.2最新定义 …

计算机网络期末重点考点总复习

第三章数据链路层 CRC检验问题 知识点 例题 要发送的数据为1101011011。采用CRC的生成多项式是 P(X)X^4 X 1试求应添加在数据后面的余数。数据在传输过程中最后一个1变成了0&#xff0c;问接收端能否发现&#xff1f; 若数据在传输过程中最后两个1都变成了0&#xff0c;问接…

MacOS系统安装Qt教程

我以为搜索QT下载&#xff0c;安装好QT Creator就能开开心心HelloWorld&#xff0c;然而还是太年轻了&#xff0c;一个 No suitable kit found 报错告诉我&#xff0c;可能没那么简单。于是&#xff0c;我去查了查&#xff0c;大概原因就是苹果处理器和x86不太一样&#xff0c;…

借助这几个工具,轻松实现在手机压缩视频

我有一个习惯&#xff0c;就是会将生活中发生的趣事&#xff0c;或是沿途好看的风景&#xff0c;用手机录制下来&#xff0c;这样的话&#xff0c;后续再回看这些视频的时候&#xff0c;就能勾起相对应的美好回忆。 但是久而久之&#xff0c;这些视频积累太多的话&#xff0c;就…

Springboot 2.7.5 HikariCP 连接池多数据源配置

一. 引言 当前项目遇到需要连接多个数据库的场景&#xff0c;此时需要引入多数据源了. 还有一些诸如以下的场景: 与第三方对接时&#xff0c;有些合作方并不会为了你的某些需求而给你开发一个功能&#xff0c;他们可以提供给你一个可以访问数据源的只读账号&#xff0c;你需要…

Web漏洞扫描篇-Nessus使用

软件介绍 Nessus是一种漏洞扫描器&#xff0c;个人和组织广泛使用它来识别和修复计算机系统中的漏洞。Nessus可以扫描广泛的漏洞&#xff0c;包括缺少补丁、弱密码和配置错误的系统&#xff0c;它可以扫描单个系统或整个网络上的漏洞。Nessus可以在各种平台上运行&#xff0c;…

【云原生进阶之容器】第一章Docker核心技术1.10节——Docker网络模型设计

1 容器网络背景概述 1.1 Linux的namespace+cgroup 先来简要回顾一下前面的内容,namespace和cgroup是Linux 内核的两大特性,namespace的诞生据说就是为了支持容器技术,那么这俩特性到底干了啥呢? - namespace:linux支持多种类型的namespace,包括Network,IPC,PID, Mount…

基于HOG、LBP完成特征工程,基于SVM/RF/XGBOOST/GBDT/CNN/DNN完成人脸识别+表情识别

在我之前的文章中写过很多关于人脸识别和表情识别的文章&#xff0c;今天有一个项目的需求就是需要做两种或者是多种任务&#xff0c;我在开发完对应的模型之后就突然想到了之前做过的人脸识别和表情识别的项目&#xff0c;就想着是否可以基于机器学习/深度学习等方式来同时实现…

算法训练第五十七天 | LeetCode 647、516动态规划结尾

LeetCode 647回文子串 题目简析&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 思路分析&#xff1a; 本题的难点 主要…

【Aptos与Sui智能合约】(Move长话短说) #03 - 智能合约编写与发布

前言:本篇学习如何在Aptos上发布两个自定义的智能合约 0x1 前置条件 安装好Aptos工具,MacOS、Ubuntu、Windows系统的预编译的安装包下载地址 https://github.com/aptos-labs/aptos-core/releases?q=cli&expanded=true 想自己从源码开始编译,你就下载Source Code 安装…

千万不要把Request传递到异步线程里面,有坑

前几天在网上冲浪的时候看到一篇技术文章&#xff0c;讲的是他把一个 request 请求传递到了线程池里面&#xff0c;然后遇到了一个匪夷所思的情况。 他写了这篇文章&#xff0c;把自己针对这个问题的探索过程分享了出来&#xff1a; 《springboot 中如何正确的在异步线程中使用…

艾美捷脂质过氧化检测试剂盒参数说明和文献参考

脂质过氧化的定量对于评估氧化损伤在病理生理学疾病中的作用至关重要。脂质过氧化导致饱和和不饱和脂质的高反应性和不稳定的氢过氧化物的形成。 艾美捷脂质过氧化检测试剂盒直接利用与亚铁离子的氧化还原反应测量过氧化氢&#xff0c;将脂质过氧化氢提取到氯仿中&#xff0c;提…

【python绘制地图——folium的方法和类的介绍(思维导图)】

Python使用folium制作地图并生成png图片 第一章 folium的方法和类的介绍&#xff08;思维导图&#xff09; 第二章 使用folium制作地图 第三章 folium实用功能进阶 第三章 使用Html2Image生成png图片 第四章 使用reportlab制作pdf报告 文章目录Python使用folium制作地图并生成…

轮廓图编程-自定义QChartView

目录 一、功能需求 二、实现效果 三、实现方法 一、功能需求 3D测量软件中&#xff0c;需要在轮廓上进行二次编程&#xff0c;需要显示轮廓线&#xff0c;然后可以调节矩形框的范围的获取参数&#xff0c;如华汉的HyperShape3D软件&#xff0c;对轮廓的编程界面如下。 二、实…

【Java基础知识复盘】String、StringBuffer、StringBuilder篇——持续更新中

本人知识复盘系列的博客并非全部原创&#xff0c;大部分摘自网络&#xff0c;只是为了记录在自己的博客方便查阅&#xff0c;往后也会陆续在本篇博客更新本人查阅到的新的知识点&#xff0c;望悉知&#xff01; String类 在 Java 中字符串属于对象&#xff0c;Java 提供了 Str…

《融合视觉显著性和局部熵的红外弱小目标检测》论文复现

1.复现论文概要 复现的论文为《融合视觉显著性和局部熵的红外弱小目标检测》&#xff08;赵鹏鹏&#xff0c;李庶中等&#xff0c;中国光学2022&#xff0c;http://www.chineseoptics.net.cn/cn/article/doi/10.37188/CO.2021-0170&#xff0c;以下简称论文&#xff09;。论文…