C++ ─── vector的实现

news2025/1/11 15:07:45

知识点:

        ① 因为vector是模版,所以声明和定义都放在.h中,防止出现编译错误

        .h不会被编译,在预处理中.h在.cpp中展开所以在编译时只有.cpp

        而 .cpp顺序编译,只会进行向上查找,因此至少有函数的声明。

        ②memcpy的复习

        memcpy(dest , source,大小)

        ③ 拷贝构造也是构造函数(拷贝构造函数我们必须写,我们写的是深拷贝)
        但是有了拷贝构造函数,编译器就不会自己生成构造函数了,
        因为拷贝构造也是构造函数的一种,所以要强制生成
        强制编译器生成默认的构造函数,使用参数的缺省值生成默认构造函数
        vector() = default;

        ④拷贝构造函数和赋值重载函数的现代写法

        ⑤扩容之后,迭代器失效问题

目录

vector.h

test.cpp


vector.h

#pragma once
#include<iostream>
#include<assert.h>
#include<algorithm>


namespace bit
{
	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;
		}

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

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


		//用迭代器区间构造函数
		//vector<int> v2(v1.begin() + 1, v1.end());
		//函数模板,写的不是iterator ,目的支持任意容器的迭代器 eg: list<int>的迭代器

		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		//构造函数,没必要自己写
		//vector()
		//:_start(nullptr)
		//,_finish(nullptr)
		//,_end_of_storage(nullptr)
		//{}
		// 拷贝构造也是构造函数(拷贝构造函数我们必须写,我们写的是深拷贝)
		// 但是有了拷贝构造函数,编译器就不会自己生成构造函数了,
        //因为拷贝构造也是构造函数的一种,所以要强制生成
		// 强制编译器生成默认的构造函数,使用参数的缺省值构造
		vector() = default;

		//n个value的构造函数
		//vector(10,10)
		// C++对内置类型也补充了内置类型的构造函数,看下面的test5中j=0
		// std::string s1("c");
		//vector(20,s1)
		vector(size_t n, const T& value = T())//T()代表用默认构造函数生成的匿名对象
		{
			reserve(n);//提高效率
			for (size_t i = 0; i < n; i++)
			{
				push_back(value);
			}
		}
		//vector<int>v4(10, 1);
		//解决编译器的选择问题
		vector(int n, const T& value = T())
		{
			reserve(n);//提高效率
			for (int i = 0; i < n; i++)
			{
				push_back(value);
			}
		}


		//拷贝构造函数
		//vector<int> v3(v2);
		vector(const vector<T>& v2)
		{
			reserve(v2.capacity());
			for (auto e: v2)
			{
				push_back(e);
			}
		}



		//赋值重载函数(利用形参时的拷贝构造生成的临时对象)
		//v3= v2;
		vector<T>& operator=( vector<T> v)//v是v2的临时拷贝,只需要将v3变成v即可(现代写法)
		{
			swap(v);
			return *this;
		}

		//析构函数
		~vector()
		{
			if (_start)
			{
				delete[]_start;
				_start = _finish = _end_of_storage = nullptr;
			}
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];

				if (_start)//不为空,拷贝原数据
				{
					memcpy(tmp, _start, sizeof(T) * size());
					delete[] _start;
				}
				_start = tmp;
				_finish = tmp + old_size;//更新_finish
				_end_of_storage = tmp + n;

			}
		}

		void resize(size_t n, const T& value = T())
		{
			if (n <= size())
			{
				_finish = _start + n;
			}
			else
			{
				if (capacity() < n)
				{
					reserve(n);
				}

				while (size() < n)
				{
					push_back(value);
				}
			}

		}

		T& operator[](size_t i)
		{
			assert(i < size());
			assert(i >= 0);
			return _start[i];
		}
		const T& operator[](size_t i) const
		{
			assert(i < size());
			assert(i >= 0);
			return _start[i];
		}

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

		void pop_back()
		{
			assert(size() > 0);
			--_finish;

		}

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}
		//在pos位置之前插入X
		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start);//不要忘了断言
			assert(pos <= _finish);

			if (_finish == _end_of_storage)//扩容会导致迭代器失效,要去更新pos
			{
				size_t length = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
				pos = _start + length;
			}
			iterator it1 = _finish;
			while (it1 != pos)//挪动数据
			{
				*(it1) = *(it1 - 1);
				--it1;
			}
			*pos = x;
			_finish++;

			return pos;
		}

		iterator erase(iterator pos)//返回擦出后的下一个
		{
			assert(pos >= _start);
			assert(pos < _finish);
			size_t len = pos - _start;
			iterator it2 = pos;
			while (it2 < _finish)
			{
				*(it2) = *(it2 + 1);
				++it2;
			}
			--_finish;
			if (size() > 0)
			{
				return _start + len;
			}
			else
			{
				return nullptr;
			}
		}

	private:
		iterator _start = nullptr;//头
		iterator _finish = nullptr;//存储内容的尾
		iterator _end_of_storage = nullptr;//存储空间的尾部
	};

	void test1()
	{
		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(6);
		v1.push_back(7);
		v1.push_back(8);
		v1.push_back(9);

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

		v1.resize(12,666);

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

		v1.resize(6);
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		std::cout << v1.size() << " " << v1.capacity() << std::endl;

		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		v1.pop_back();
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		std::cout << v1.size() << " " << v1.capacity() << std::endl;
		/*v1.pop_back();*/
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		std::cout << v1.size() << " " << v1.capacity() << std::endl;
	}
	void test2()
	{
		vector<int> v1;

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

		v1.insert(v1.begin(), 10);
		v1.insert(v1.end(), 20);
		v1.insert(v1.end(), 30);
		v1.insert(v1.end(), 40);
		v1.insert(v1.end(), 50);
		v1.insert(v1.end(), 60);

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

		v1.erase(v1.end()-1);
		v1.erase(v1.end()-1);
		int* it = v1.erase(v1.begin());
		std::cout << *it;
		/*	for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		std::cout << v1.size() << " " << v1.capacity() << std::endl;*/

	}
	void test3()
	{
		vector<int> v1;
		v1.push_back(10);
		v1.push_back(20);
		v1.push_back(30);
		v1.push_back(40);
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

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


	}
	void test4()
	{
		vector<int> v1;
		v1.push_back(10);
		v1.push_back(20);
		v1.push_back(30);
		v1.push_back(40);
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

		vector<int> v2(v1.begin() + 1, v1.end());
		for (auto e : v2)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
	}
	void test5()
	{
		int x = 0;
		int k = int();
		int j(10);
		std::cout << x << " " << j << " " << k << std::endl;
	}
	void test6()
	{
		std::string s1("c");
		vector<std::string> v1(5);//第二个参数省略,用缺省值
		vector<std::string>v2(5, s1);

		vector<std::string>v3(5, "aa");
		//vector<std::string>v3(5, 1);会报错,系统认为与template<class InputIterator>更匹配
										//vector(InputIterator first,InputIterator last)
		vector<int> v4((size_t)5, 1);//5u指的是unsigned_int
		for (auto e : v1)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		for (auto e : v2)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		for (auto e : v3)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
		for (auto e : v4)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

		vector<int> v5(10, 1);
		for (auto e : v5)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
	}

}

test.cpp

#include"vector.h"


int main()
{
	bit::test6();
	return 0;
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

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

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

相关文章

【Linux】进程 | 控制块pcb | task_struct | 创建子进程fork

目录 Ⅰ. 进程的概念&#xff08;Process&#xff09; 1. 什么是进程&#xff1f; 2. 多进程管理 3. 进程控制块&#xff08;PCB&#xff09; task_struct 的结构 Ⅱ. 进程查看与管理 1. 使用指令查看进程 2. /proc 查看进程信息 3. 获取进程 ID 4. 创建子进程 原因…

在Ubuntu22.04 使用stable-diffusion-webui 秋叶整合包

背景 众所周知&#xff0c;赛博菩萨已经发布了windows下的整合包&#xff0c;开箱即用&#xff0c;且集成度较高。 那我为啥非要在Ubuntu下使用呢&#xff1f; 当然是因为主力机就是Ubuntu系统啦。而且涉及到sd webui API 的调用&#xff0c;在Ubuntu 下调试更加方便一点。 那…

PG实践|内置函数之GENERATE_SERIES之深入理解

&#x1f4eb; 作者简介&#xff1a;「六月暴雪飞梨花」&#xff0c;专注于研究Java&#xff0c;就职于科技型公司后端工程师 &#x1f3c6; 近期荣誉&#xff1a;华为云云享专家、阿里云专家博主、腾讯云优秀创作者、ACDU成员 &#x1f525; 三连支持&#xff1a;欢迎 ❤️关注…

2024年第十五届蓝桥杯青少组大赛8月24日开启

据蓝桥杯青少组官网显示&#xff0c;2024年第十五届蓝桥杯青少组大赛8月24日开启。 蓝桥杯青少组历届题库地址&#xff1a;http://www.6547.cn/question/cat/2 蓝桥杯青少组历届真题下载&#xff1a;http://www.6547.cn/wenku/list/10

【神经网络】CNN网络:深入理解卷积神经网络

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&#xff01; CNN网络&#xff1a;深入理解…

VideoLLaMA 2:多模态视频理解新突破,音频理解能力再升级,挑战 GPT-4V

前言 近年来&#xff0c;人工智能技术飞速发展&#xff0c;尤其是大模型的出现&#xff0c;为视频理解和生成领域带来了前所未有的机遇。然而&#xff0c;现有的视频大模型&#xff08;Video-LLM&#xff09;在处理视频中复杂的时空信息和音频信息方面仍存在不足&#xff0c;例…

【C++11(二)】lambda表达式和可变参数模板

一、可变参数模板 C11的新特性可变参数模板 能够让您创建可以接受 可变参数的函数模板和类模板 // Args是一个模板参数包&#xff0c;args是一个函数形参参数包 // 声明一个参数包Args...args&#xff0c;这个参数包中可以包含0到任意个模板参数。 template <class ...Arg…

笔记101:OSQP求解器的底层算法 -- ADMM算法

前言1&#xff1a;这篇博客仅限于介绍拉格朗日乘子法&#xff0c;KKT条件&#xff0c;ALM算法&#xff0c;ADMM算法等最优化方法的使用以及简版代码实现&#xff0c;但不会涉及具体的数学推导&#xff1b;不过在下面我会给出具体数学推导的相关文章和截图&#xff0c;供学有余力…

Elasticsearch:使用 Llamaindex 的 RAG 与 Elastic 和 Llama3

这篇文章是对之前的文章 “使用 Llama 3 开源和 Elastic 构建 RAG” 的一个补充。我们可以在本地部署 Elasticsearch&#xff0c;并进行展示。我们将一步一步地来进行配置并展示。你还可以参考我之前的另外一篇文章 “Elasticsearch&#xff1a;使用在本地计算机上运行的 LLM 以…

在线epub阅读器epub;在线图书阅读器;专门为epub定制的阅读器;免费在线电子图书epub阅读器

背景&#xff1a;不记得某时某刻了&#xff0c;就是当时想要使用电脑阅读epub图书&#xff0c;也找了好些个在线epub阅读器&#xff0c;但总有一些不如意的地方&#xff0c;如某些功能需要会员之类的&#xff0c;突发临想的就想到自己开发一个&#xff0c;就此&#xff0c;一个…

大模型RAG技术:构建高效、可信赖的知识检索系统

前言 LLM 问题 幻觉&#xff1a;在没有答案的情况下提供虚假信息。 过时&#xff1a;当用户需要特定的当前响应时&#xff0c;提供过时或通用的信息。 来源&#xff1a;从非权威来源创建响应。由于术语混淆&#xff0c;不同的培训来源使用相同的术语来谈论不同的事情&#…

C# Onnx Yolov8-OBB 旋转目标检测 行驶证副页条码+编号 检测,后续裁剪出图片并摆正显示

C# Onnx Yolov8-OBB 旋转目标检测 行驶证副页条码编号 检测&#xff0c;后续裁剪出图片并摆正显示 目录 效果 模型信息 项目 代码 下载 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-06-25T10:59:15.206586 description&#xff1a;…

第一课:SSH协议、SSHD守护进程、Openssh软件包

第一节课 6月12日 ssh协议 关键问题 一、ssh、sshd、openssh的概念和区别&#xff1f; 二、ssh是基于什么架构&#xff1f;B/S还是C/S&#xff1f; 三、用户远程连接服务器经历哪些过程&#xff1f; 四、如何查看openssh软件包是否安装&#xff1f; 五、rpm和yum的区别&#xf…

node带参数命令

不带参数命令示例&#xff1a; node /www/wwwroot/server 带参数命令示例&#xff1a; node /www/wwwroot/server arg1 arg2 arg3 在启动页进行参数处理&#xff1a; // 获取启动参数(除去前2个默认参数&#xff0c;示例&#xff1a;node /www/wwwroot/server arg1 arg2 …

SAP ABAP 之容器

文章目录 前言一、案例介绍/笔者需求二、自定义容器 a.实例化对象 b.自定义容器效果演示 c.Copy Code 三、自适应容器 a.常用 必须 参数理解 b.METRIC 度量单位 c.RATIO 百分比尺寸 d.STYLE 容器…

WMV 视频格式怎么转换?WMV 视频为什么不流行了?

目前有越来越多的视频格式类型&#xff0c;如常见的 MP4、FLV、AVI 等等&#xff0c;而技术的演变也逐渐让一些常见的视频格式变的越来越少了。 今天我们一起来聊下 WMV 这个视频格式&#xff0c;让我们看看它的发展以及为什么现在越来越少人使用了。 什么是 WMV 视频格式&…

微信营销自动化(朋友圈自动点赞工具):UIAutomation的解决方案

文章不用看, 是AI生成的, 请直接查看下载地址 http://www.aisisoft.top . 微信朋友圈自动点赞工具, 自动群发工具 在当今的数字化营销领域&#xff0c;自动化工具成为了提升工作效率、增强客户互动的关键。本文将详细介绍一款基于UIAutomation框架与Python语言构建的微信营销自…

数据容器(四)

目录 一、dict&#xff08;字典、映射&#xff09; 1.字典的定义 2.字典数据的获取 3.字典的嵌套 一、dict&#xff08;字典、映射&#xff09; 1.字典的定义 使用{}&#xff0c;不过存储的元素是一个个的&#xff1a;键值对。 2.字典数据的获取 字典同集合一样&#xff…

PointCloudLib-滤波模块(Filtering)-使用统计异常值移除过滤器移除异常值

在本教程中,我们将学习如何消除噪声测量值,例如异常值, 使用统计分析技术的点云数据集。 背景 激光扫描通常会生成不同点密度的点云数据集。 此外,测量误差会导致稀疏异常值,从而破坏 结果更多。这使得本地点云的估计变得复杂 表面法线或曲率变化等特征,导致 错误的值,…

【WEB】关于react的WEB应用中使用React Developer Tools便捷快速查看元素数据

1、往扩展工具中添加React Developer Tools的扩展包 2、检查是否生效&#xff0c;如下图&#xff1a; 可以看到右上角多出来一个Components的tab选项&#xff0c;就是成功了