【C++】vector 常用成员函数的模拟实现

news2024/9/28 23:26:31

【C++】vector 常用成员函数的模拟实现

  • 1. vector 常用成员函数的模拟实现
  • 2. vector 常用成员函数实现后的测试

1. vector 常用成员函数的模拟实现

2. vector 常用成员函数实现后的测试

#include<assert.h>
#include<iostream>
#include<string>
using std::cout;
using std::endl;
using std::string;

//自定义命名空间wch
namespace wch
{
	//vector要支持不同类型元素,所以用模板
	template<class T>

	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

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

		// vector<int> v(10, 1);//如果无函数vector(int n, const T& val = T()),
		//因为参数类型更匹配,会去调用vector(InputIterator first, InputIterator last)
		// 但是函数内部有解引用(*first),整形不可解引用,导致报错
		vector(size_t n, const T& val = T())
		{
			resize(n, val);
		}
		vector(int n, const T& val = T())
		{
			resize(n, val);
		}

		// [first, last)迭代器,采用区间初始化
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		//由于声明时已经初始化给予了缺省参数,所以此处不写初始化列表初始化
		vector()
		{}

		//原始方法实现拷贝构造函数
		vector(const vector<T>& v)
		{
			_start = new T[v.capacity()];
			//memcpy(_start, v._start, sizeof(T)*v.size());//浅拷贝,部分自定义类型无法达到目的

			//深拷贝
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];
			}

			_finish = _start + v.size();
			_endofstorage = _start + v.capacity();
		}

		//现代方法拷贝构造
		/*vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}*/

		void swap(vector<T>& v)
		{
			//注意这里用的是库函数swap,因为我们这里是在自己实现vector成员函数
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		// v1 = v2,赋值运算符重载
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

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

		void reserve(size_t n)
		{
			//要加判断,因为当n<capacity时,不需要做处理
			if (n > capacity())
			{
				//这里需要先保存大小,因为开辟新空间后,成员函数size里的地址_finish还指向销毁的旧空间,
				//无法正确完成_finish的更新
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * sz);//浅拷贝
		
					//深拷贝
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}

					delete[] _start;
				}

				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		//缺省参数T(),当缺省参数为自定义类型,T()为匿名对象,会去调用构造函数
		//内置类型如:int与int()无差别
		void resize(size_t n, const T& val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				//多余有效空间用val初始化
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		void push_back(const T& x)
		{
			/*if (_finish == _endofstorage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			*_finish = x;
			++_finish;*/
			insert(end(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

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

		size_t size() const
		{
			return _finish - _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];
		}

		//返回插入元素地址
		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);

			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;// 解决pos迭代器失效问题

				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);

				// 需要更新pos,因为扩容过后pos还指向旧空间,即解决pos迭代器失效问题
				pos = _start + len;
			}

			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}

			*pos = x;
			++_finish;

			return pos;
		}

		//返回删除元素地址
		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);

			iterator it = pos + 1;
			while (it != _finish)
			{
				*(it - 1) = *it;
				++it;
			}

			--_finish;

			return pos;
		}

	private:
		//给予缺省参数
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;
	};

	void print(const vector<int>& v)
	{
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	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;

		for (size_t i = 0; i < v1.size(); i++)
		{
			v1[i]++;
		}

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

		print(v1);
	}

	void test_vector2()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		v1.push_back(5);
		v1.push_back(5);
		v1.push_back(5);

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

		v1.insert(v1.begin(), 100);

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

		/*vector<int>::iterator p = v1.begin() + 3;
		v1.insert(p, 300);*/

		vector<int>::iterator p = v1.begin() + 3;
		//v1.insert(p+3, 300);

		// insert以后迭代器可能会失效(扩容)
		// 记住,insert以后就不要使用这个形参迭代器了,因为他可能失效了
		v1.insert(p, 300);

		// 高危行为
		// *p += 10;

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

	void test_vector3()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		v1.push_back(6);

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

		auto it = v1.begin();
		while (it != v1.end())
		{
			if (*it % 2 == 0)
			{
				it = v1.erase(it);
			}
			else
			{
				++it;
			}
		}

		//v1.erase(v1.begin());
		//auto it = v1.begin()+4;
		//v1.erase(it);

		 erase以后,迭代器失效了,不能访问
		 vs进行强制检查,访问会直接报错
		//cout << *it << endl;
		//++it;
		//cout << *it << endl;

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

	void test_vector4()
	{
		vector<int> v;
		v.resize(10, 0);

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

		int i = 0;
		int j = int();//i = 0;
		int k = int(1);//k = 1;
	}

	void test_vector5()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

		vector<int> v1(v);

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

		vector<int> v2;
		v2.resize(10, 1);

		v1 = v2;
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector6()
	{
		vector<string> v;
		v.push_back("111111111111111111");
		v.push_back("222222222222222222");
		v.push_back("333333333333333333");
		v.push_back("444444444444444444");
		v.push_back("555555555555555555");

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

		vector<string> v1(v);
		for (auto& e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_vector7()
	{
		vector<int> v(10, 1);
		vector<string> v1(10, "1111");
		vector<int> v2(10, 1);

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

		vector<int> v3(v.begin(), v.end());
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		string str("hello world");
		vector<char> v4(str.begin(), str.end());
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;

		int a[] = { 16,2,77,29 };
		vector<int> v5(a, a + 4);
		for (auto e : v5)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

int main()
{
	//wch::test_vector1();
	//wch::test_vector2();
	//wch::test_vector3();
	//wch::test_vector4();
	//wch::test_vector5();
	//wch::test_vector6();
	wch::test_vector7();

	return 0;
}

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

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

相关文章

Spring--boot自动配置原理案例--阿里云--starter

Spring–boot自动配置原理案例–阿里云–starter 定义这个starter的作用是它可以将阿里云的工具类自动放入IOC容器中&#xff0c;供人使用。 我们看一看构建starter的过程&#xff0c;其实就是在atuoconfigure模块中加入工具类&#xff0c;然后写一个配置类在其中将工具类放入…

【ChromeDriver安装】爬虫必备

以下是安装和配置 chromedriver 的步骤&#xff1a; 1. 确认 Chrome 浏览器版本 打开 Chrome 浏览器&#xff0c;点击右上角的菜单按钮&#xff08;三个点&#xff09;&#xff0c;选择“帮助” > “关于 Google Chrome”。 2. 下载 Chromedriver 根据你的 Chrome 版本&…

【研赛A题成品论文】24华为杯数学建模研赛A题成品论文+可运行代码丨免费分享

2024华为杯研究生数学建模竞赛A题精品成品论文已出&#xff01; A题 风电场有功功率优化分配 一、问题分析 A题是一道工程建模与优化类问题&#xff0c;其目的是根据题目所给的附件数据资料分析风机主轴及塔架疲劳损伤程度&#xff0c;以及建立优化模型求解最优有功功率分配…

哪些AI软件能轻松搞定你的文案、总结、论文、计划书?

大家好&#xff01;在我们每天紧张忙碌的生活中&#xff0c;有时候一天结束时&#xff0c;我们还有一堆事情等着处理。 图片 但别担心&#xff0c;今天我要为大家介绍几款AI软件&#xff0c;它们可以在你忙碌的一天结束后&#xff0c;成为你的得力助手&#xff0c;帮你轻松管…

初识Tomcat

Tomcat是一款可以运行javaWebAPP的服务器软件。 一个服务器想要执行java代码&#xff0c;则需要JRE&#xff08;jvm、java运行环境等&#xff09;&#xff0c;但是需要执行javaWEB项目则还需要服务器软件&#xff0c;Tomacat就是其中很流行的一款。因为一个javaWEB项目会有很多…

Accelerate单卡,多卡config文件配置

依赖库 from accelerate import Accelerator from accelerate import DistributedDataParallelKwargs ddp_kwargs DistributedDataParallelKwargs(find_unused_parametersTrue) accelerator Accelerator(kwargs_handlers[ddp_kwargs]) 代码中删除所有的.cuda() 或者to(devic…

Xshell连接服务器

一、Xshell-7.0.0164p、Xftp 7下载 1.1、文件下载 通过网盘分享的文件&#xff1a;xshell 链接: https://pan.baidu.com/s/1qc0CPv4Hkl19hI9tyvYZkQ 提取码: 5snq –来自百度网盘超级会员v2的分享 1.2、ip连接 下shell和xftp操作一样&#xff1a;找到文件—》新建—》名称随…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,1-1

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…

论文不同写作风格下的ChatGPT提示词分享

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 在学术论文写作中&#xff0c;不同的写作风格能显著影响文章的表达效果与读者的理解。无论是描述性、分析性、论证性&#xff0c;还是批判性写作风格&#xff0c;合理选择和运用恰当的写…

生成模型小结

突然发现之前整理的makedown有必要放在博客里面,这样不同的设备之间可以直接观看达到复习的效果. GAN G和D不断的博弈提高自己。GAN的优点是保真度比较高&#xff0c;缺点是多样性比较低。 (auto-encoder)AE&#xff0c;DAE、VAE、VQVAE 输入x&#xff0c;经过编码器生成&…

Elasticsearch学习笔记(2)

索引库操作 在Elasticsearch中&#xff0c;Mapping是定义文档字段及其属性的重要机制。 Mapping映射属性 type&#xff1a;字段数据类型 1、字符串&#xff1a; text&#xff1a;可分词的文本&#xff0c;适用于需要全文检索的情况。keyword&#xff1a;用于存储精确值&am…

二阶低通滤波器(Simulink仿真)

1、如何将S域传递函数转为Z域传递函数 传递函数如何转化为差分方程_非差分方程转成差分方程-CSDN博客文章浏览阅读4.1k次,点赞4次,收藏50次。本文介绍了如何将传递函数转化为差分方程,主要适用于PLC和嵌入式系统。通过MATLAB的系统辨识工具箱获取传递函数,并探讨了离散化方…

OpenCV第十二章——人脸识别

1.人脸跟踪 1.1 级联分类器 OpenCV中的级联分类器是一种基于AdaBoost算法的多级分类器&#xff0c;主要用于在图像中检测目标对象。以下是对其简单而全面的解释&#xff1a; 一、基本概念 级联分类器&#xff1a;是一种由多个简单分类器&#xff08;弱分类器&#xff09;级联组…

Yolov10环境配置

参考文章&#xff1a;1.YOLOv10超详细环境搭建以及模型训练&#xff08;GPU版本&#xff09;-CSDN博客 2.Windows下安装pytorch教程(下载.whl的方式)_pytorch whl-CSDN博客 安装步骤和文件夹顺序一样 1.安装CUDA和cuDNN 1.1安装CUDA 1.1.1查看当前你的电脑显卡支持的最高CUD…

Docker从入门到精通_02 Docker魔法之旅:零基础Linux用户也能轻松驾驭的安装部署指南

文章目录 Docker从入门到精通_02 Docker魔法之旅&#xff1a;零基础Linux用户也能轻松驾驭的安装部署指南一 操作系统安装二 操作系统环境准备2.1 关闭防火墙2.1.2.2 关闭selinux2.2.1 临时关闭selinux2.2.2 永久关闭selinux 三 docker引擎安装3.1 从get.docker.com 下载 get-d…

02-ZYNQ linux开发环境安装,基于Petalinux2022.2和Vitis2022.2

petalinux安装 Petalinux 工具是 Xilinx 公司推出的嵌入式 Linux 开发套件&#xff0c;包括了 u-boot、Linux Kernel、device-tree、rootfs 等源码和库&#xff0c;以及 Yocto recipes&#xff0c;可以让客户很方便的生成、配置、编译及自定义 Linux 系统。Petalinux 支持 Ver…

了解 如何使用同快充充电器给不同设备快速充电

在这科技发展迅速的时代&#xff0c;快充技术已经走进了我们生活&#xff0c;不得不说有了快充技术的对比&#xff0c;传统的充电模式已经满足不了人们对充电速度的要求。就比如用华为输出100 W快充充电器为手机充电大概需要23分钟充满100%电量&#xff0c;而传统的充电器则需要…

可以免费制作表情包的AI工具来了!

一直想自己制作一套表情包&#xff0c;但一直没有找到好用的工具&#xff0c;要么就是太麻烦&#xff0c;要么就是不免费。 今天AI表情包免费制作工具来了&#xff0c;手机就可以直接做表情包&#xff0c;非常方便。 先看效果~ 工具用到的是通义APP&#xff0c;可以在频道中找…

车辆重识别(利用扩散模型合成有效数据进行行人再识别预训练)论文阅读2024/9/27

[1]Synthesizing Efficient Data with Diffusion Models for Person Re-Identification Pre-Training 作者&#xff1a;Ke Niu1, Haiyang Yu1, Xuelin Qian2, Teng Fu1, Bin Li1, Xiangyang Xue1*单位&#xff1a;1复旦大学, 2西北工业大学 摘要&#xff1a; 现有的行人重识别…

若伊(前后端分离)学习笔记

基础应用篇 1. 若伊搭建 若伊版本 若依官方针对不同开发需求提供了多个版本的框架&#xff0c;每个版本都有其独特的特点和适用场景&#xff1a; 前后端混合版本 &#xff1a;RuoYi结合了SpringBoot和Bootstrap的前端开发框架&#xff0c;适合快速构建传统的Web应用程序&…