C++_STL之vector篇

news2025/4/1 12:51:42

一、vector的常见用法

        注:C++中若使用vector需包含头文件<vector>.

1.vector的构造函数

	int n = 10,ret=1;
	vector<int> nums(n,ret);	//n表示vector初始的容量 ret表示vector中初始化的值
	for (auto e : nums)
		cout << e << " ";

扩展:vector<type>可以放入任意类型

如vector<vector<int> >,vecotr<string>,vector<pair<int,int> >等,效果是一样的;

2.迭代器

在现在的大多数编译器中是支持vector使用迭代器的,如图所示

3.拷贝构造

        vector的拷贝构造具有很好的实用性,需要创建一个原数组的临时变量时,这个函数就极大减少了我们创建新vector进行赋值的时间,与此同时,我们还可以对其中一项vector进行赋值操作,如下面注释内容中v=nums(此处的 = 为我们的运算符重载)。

	int n = 4,m=5,ret=6;
	vector<vector<int>> nums(n,vector<int>(m,ret));	
    //n,m表示vector初始的容量 ret表示vector中初始化的值
	
	vector<vector<int> > v(nums);		//将nums内容拷贝到v上
	//常见写法vector<vector<int> > v;
	//v=nums;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cout << v[i][j] << " ";
		}
		cout << endl;
	}

4.reserve(size_t n)函数

        reserve函数是一个预扩容函数,可以为vector对象重新扩容,从而提高了vector的性能,在后面的insert函数和push_back等函数中会用到reserve这个函数。

5.resize(size_t n, const T& val = T())

        resize的功能就是重置数组的大小。功能效果如图所示

6.push_back(const T& x)

        push_back的功能就是在vector后面插入一个数据x,vector长度会自动+1,capacity(容量)不足时会自动扩容(注:这里的扩容量不定,是由编译器内部实现决定的)。效果图如下:

7.pop_back()

        这个函数的功能就是删除vector中最后一项元素,vector长度-1。效果图如下:

8.[size_t pos]运算符重载

        该函数的功能是返回vector容器中pos位置元素的值(引用返回),因此这里我们就既可以查看pos位置的值也可以修改pos位置的值;效果图:

9.insert(iterator pos, const T& x)

        功能在pos位置(此处的pos为迭代器插入方式应为nums.insert(nums.begin()+pos,x) )插入x值,由于每次插入一般都需移动vector时间成本高,所以在算法题中比较少见。(算法中常用push_back());用法如图所示:

10.erase(iterator pos)

        功能在pos位置(此处的pos为迭代器插入方式应为nums.erase(nums.begin()+pos) )删除x值,由于每次删除一般都需移动vector时间成本高,所以在算法题中比较少见。(算法中常用pop_back());用法如图所示:

11.size()

        这个函数非常实用无论是在算法题上,还是在自己敲代码时实现某些功能时这个函数都很常见,功能就是得到vector的长度。效果图:

12.capacity()

        这个函数在做算法题时不怎么常用,但还是需要了解一下。显而易见,功能就是得到vector的容量大小。效果图:

二、vector的模拟实现

由STL库中可见,vector内部是由三个指针来实现的:

        _start所在位置为vector起始位置;

        _finish所在位置为vector长度终止位置及size+1处;

        _endofstorage所在位置为vector容量终止位置。

1.vector内部值初始化

namespace lwf 
{
	template <class T>
	class vector
	{
	public:
		typedefy T* iterator;
		typedefy const T* const_iterator;
	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstoage = nullptr;
	};
}

2.vector的构造函数

        vector(size_t n, const T& val = T())
		{
			resize(n, val);
		}

		vector(int n, const T& val = T())
		{
			resize(n, val);
		}

3.迭代器

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}
        //const 迭代器
		const_iterator begin()const
		{
			return _start;
		}

		const_iterator end()const
		{
			return _finish;
		}
        //迭代器的实现
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

4.拷贝构造

		//拷贝构造
		vector(const vector<T>& v)
		{
			_start = new T[v.capacity()];
			for (size_t i = 0; i < v._size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_endofstorage = _start + v.capacity();
		}

		void swap(vector<T> v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		vector operator=(vector<T> v)
		{
			swap(v);

			return *this;
		}

5.reserve(size_t n)函数

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					for (size_t i = 0; i < size(); i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

6.resize(size_t n, const T& val = T())

		void resize(size_t n, const T& val = T())
		{
			if (n > size())
			{
				reserve(n);
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else
			{
				_finish = _start + n;
			}
		}

7.push_back(const T& x)

		void push_back(const T& x)
		{
			insert(end(), x);
		}

8.pop_back()

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

9.[size_t pos]运算符重载

		T& operator[](size_t pos)
		{
			assert(pos < size());
			return _start[pos];
		}
        //const 类型
		const T& operator[](size_t pos)const
		{
			assert(pos < size());
			return _start[pos];
		}

10.insert(iterator pos, const T& x)

		iterator insert(iterator pos, const T& x)
		{
			assert(pos <= _finish && pos >= _start);
			if (_finish == _endofstorage)
			{
				size_t len = pos-_start;
				size_t newcapacity= capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);

				//解决迭代器失效问题
				pos = _start + len;
			}

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

			return pos;
		}

11.erase(iterator pos)

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator it = pos + 1;
			while (pos != _finish)
			{
				*(pos - 1) = *pos;
				++pos;
			}
			--_finish;

			return pos;
		}

12.size()

		size_t size()
		{
			return _finish - _start;
		}

13.capacity()

		size_t capacity()
		{
			return _endofstorage - _start;
		}

14.析构函数

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

三、整体的实现

        整体的代码仅供参考,只是为了加强自己的记忆力和代码能力,从而个人实现了vector的一些基础的功能

#pragma once

#include <assert.h>

namespace lwf
{
	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 capacity()
		{
			return _endofstorage - _start;
		}

		size_t size()
		{
			return _finish - _start;
		}

		vector(size_t n, const T& val = T())
		{
			resize(n, val);
		}

		vector(int n, const T& val = T())
		{
			resize(n, val);
		}

		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()];
			for (size_t i = 0; i < v._size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_endofstorage = _start + v.capacity();
		}

		void swap(vector<T> v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		vector operator=(vector<T> v)
		{
			swap(v);

			return *this;
		}

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

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					for (size_t i = 0; i < size(); i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		void resize(size_t n, const T& val = T())
		{
			if (n > size())
			{
				reserve(n);
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else
			{
				_finish = _start + n;
			}
		}

		void push_back(const T& x)
		{
			insert(end(), x);
		}

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

		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 <= _finish && pos >= _start);
			if (_finish == _endofstorage)
			{
				size_t len = pos-_start;
				size_t newcapacity= capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);

				//解决迭代器失效问题
				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 (pos != _finish)
			{
				*(pos - 1) = *pos;
				++pos;
			}
			--_finish;

			return pos;
		}
	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;
	};
	
}

四、感言

        由于一些学业上的原因断更了半个学期,在这里感谢各位大佬和友友们的支持,不介意的话给我点个赞再走吧!

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

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

相关文章

sqli-labs靶场 less 9

文章目录 sqli-labs靶场less 9 时间盲注 sqli-labs靶场 每道题都从以下模板讲解&#xff0c;并且每个步骤都有图片&#xff0c;清晰明了&#xff0c;便于复盘。 sql注入的基本步骤 注入点注入类型 字符型&#xff1a;判断闭合方式 &#xff08;‘、"、’、“”&#xf…

【Golang】第八弹----面向对象编程

&#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;Golang &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 前言&#xff1a;Go语言面向对象编程说明 Golang也支持面向对…

java基础以及内存图

java基础 命名&#xff1a; 大驼峰&#xff1a;类名 小驼峰&#xff1a;变量名方法名等其他的 全部大写&#xff1a;常量名字.. // 单行注释 /**/ 多行注释 变量类型 变量名 一、基本类型&#xff08;8个&#xff09; 整数&#xff1a;byte-8bit short-16bit int 32-b…

【嵌入式学习3】TCP服务器客户端 - UDP发送端接收端

目录 1、TCP TCP特点 TCP三次握手&#xff08;建立TCP连接&#xff09;&#xff1a; TCP四次握手【TCP断开链接的时候需要经过4次确认】&#xff1a; TCP网络程序开发流程 客户端开发&#xff1a;用户设备上的程序 服务器开发&#xff1a;服务器设备上的程序 2、UDP 为…

Linux之基础知识

目录 一、环境准备 1.1、常规登录 1.2、免密登录 二、Linux基本指令 2.1、ls命令 2.2、pwd命令 2.3、cd命令 2.4、touch命令 2.5、mkdir命令 2.6、rmdir和rm命令 2.7man命令 2.8、cp命令 2.9、mv命令 2.10、cat命令 2.11、echo命令 2.11.1、Ctrl r 快捷键 2…

llamafactory微调效果与vllm部署效果不一致如何解决

在llamafactory框架训练好模型之后&#xff0c;自测chat时模型效果不错&#xff0c;但是部署到vllm模型上效果却很差 这实际上是因为llamafactory微调时与vllm部署时的对话模板不一致导致的。 对应的llamafactory的代码为 而vllm启动时会采用大模型自己本身设置的对话模板信息…

WebSocket通信的握手阶段

1. 客户端建立连接时&#xff0c;通过 http 发起请求报文&#xff0c;报文表示请求服务器端升级协议为 WebSocket&#xff0c;与普通的 http 请求协议略有区别的部分在于如下的这些协议头&#xff1a; 上述两个字段表示请求服务器端升级协议为 websocket 协议。 2. 服务器端响…

分布式ID服务实现全面解析

分布式ID生成器是分布式系统中的关键基础设施&#xff0c;用于在分布式环境下生成全局唯一的标识符。以下是各种实现方案的深度解析和最佳实践。 一、核心需求与设计考量 1. 核心需求矩阵 需求 重要性 实现难点 全局唯一 必须保证 时钟回拨/节点冲突 高性能 高并发场景…

dom0运行android_kernel: do_serror of panic----failed to stop secondary CPUs 0

问题描述&#xff1a; 从日志看出,dom0运行android_kernel&#xff0c;刚开始运行就会crash,引发panic 解决及其原因分析&#xff1a; 最终问题得到解决&#xff0c;发现是前期在调试汇编阶段代码时&#xff0c;增加了汇编打印的指令&#xff0c;注释掉这些指令,问题得到解决。…

HarmonyOS NEXT——【鸿蒙原生应用加载Web页面】

鸿蒙客户端加载Web页面&#xff1a; 在鸿蒙原生应用中&#xff0c;我们需要使用前端页面做混合开发&#xff0c;方法之一是使用Web组件直接加载前端页面&#xff0c;其中WebView提供了一系列相关的方法适配鸿蒙原生与web之间的使用。 效果 web页面展示&#xff1a; Column()…

优选算法的慧根之翼:位运算专题

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 一、位运算 基础位运算 共包含6种&(按位与&#xff0c;有0就是0)、|(按位或有1就是1)、^(按位异或&#xff0c;相同为0&#xff0c;相异为1)、~(按位取反&#xff0c;0变成1&#xff0c;1变成0)、<<(左…

图论问题集合

图论问题集合 寻找特殊有向图&#xff08;一个节点最多有一个出边&#xff09;中最大环路问题特殊有向图解析算法解析步骤 1 &#xff1a;举例分析如何在一个连通块中找到环并使用时间戳计算大小步骤 2 &#xff1a;抽象成算法注意 实现 寻找特殊有向图&#xff08;一个节点最多…

【数据结构】栈 与【LeetCode】20.有效的括号详解

目录 一、栈1、栈的概念及结构2、栈的实现3、初始化栈和销毁栈4、打印栈的数据5、入栈操作---栈顶6、出栈---栈顶6.1栈是否为空6.2出栈---栈顶 7、取栈顶元素8、获取栈中有效的元素个数 二、栈的相关练习1、练习2、AC代码 个人主页&#xff0c;点这里~ 数据结构专栏&#xff0c…

Redis设计与实现-哨兵

哨兵模式 1、启动并初始化sentinel1.1 初始化服务器1.2 使用Sentinel代码1.3 初始化sentinel状态1.4 初始化sentinel状态的master属性1.5 创建连向主服务器的网络连接 2、获取主服务器信息3、获取从服务器的信息4、向主从服务器发送信息5、接受主从服务器的频道信息6、检测主观…

C++进阶——封装哈希表实现unordered_map/set

与红黑树封装map/set基本相似&#xff0c;只是unordered_map/set是单向迭代器&#xff0c;模板多传一个HashFunc。 目录 1、源码及框架分析 2、模拟实现unordered_map/set 2.1 复用的哈希表框架及Insert 2.2 iterator的实现 2.2.1 iteartor的核心源码 2.2.2 iterator的实…

【算法day25】 最长有效括号——给你一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

32. 最长有效括号 给你一个只包含 ‘(’ 和 ‘)’ 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 https://leetcode.cn/problems/longest-valid-parentheses/ 2.方法二&#xff1a;栈 class Solution { public:int longestValid…

Jenkins + CICD流程一键自动部署Vue前端项目(保姆级)

git仓库地址&#xff1a;参考以下代码完成,或者采用自己的代码。 南泽/cicd-test 拉取项目代码到本地 使用云服务器或虚拟机采用docker部署jenkins 安装docker过程省略 采用docker部署jenkins&#xff0c;注意这里的命令&#xff0c;一定要映射docker路径&#xff0c;否则无…

一款超级好用且开源免费的数据可视化工具——Superset

认识Superset 数字经济、数字化转型、大数据等等依旧是如今火热的领域&#xff0c;数据工作有一个重要的环节就是数据可视化。 看得见的数据才更有价值&#xff01; 现如今依旧有多数企业号称有多少多少数据&#xff0c;然而如果这些数据只是呆在冷冰冰的数据库或文件内则毫无…

RedHatLinux(2025.3.22)

1、创建/www目录&#xff0c;在/www目录下新建name和https目录&#xff0c;在name和https目录下分别创建一个index.htm1文件&#xff0c;name下面的index.html 文件中包含当前主机的主机名&#xff0c;https目录下的index.htm1文件中包含当前主机的ip地址。 &#xff08;1&…

【C++篇】类与对象(上篇):从面向过程到面向对象的跨越

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…