【C++进阶(二)】STL大法--vector的深度剖析以及模拟实现

news2024/11/26 0:10:39

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

vector

  • 1. 前言
  • 2. 熟悉vector的接口函数
    • 2.1 vector的构造与拷贝构造
    • 2.2 vector迭代器的使用
    • 2.3 vector空间相关函数
    • 2.4 vector的增删查改
      • 2.41 find,swap和sort
      • 2.42 insert和erase
      • 2.43 随机访问operator[ ]
  • 3. vector的模拟实现
    • 3.1 vector容量相关函数
    • 3.11 reverse函数
      • 3.12 resize函数
    • 3.2 vector的构造函数
    • 3.3 vector的析构函数
    • 3.4 vector的拷贝构造函数
  • 4. 总结以及拓展

1. 前言

和string的学习不同
vector即要掌握它的用法
更要会自己去实现一个vector

本章重点:

熟悉STL库中vector的接口函数
自己实现一个简易vector类
本章只实现容量相关函数
和构造,析构,拷贝构造函数

注:vector其实就是顺序容器
string类只用考虑存储字符
然而vector中可以存储任一类型
所以vector的自我实现需要用模板


2. 熟悉vector的接口函数

还是借助老朋友:cplusplus来查阅文档

在这里插入图片描述

库中的vector的模板参数有两个
后一个是内存池,用来提升空间利用效率
对于现阶段的学习而言可有可无


2.1 vector的构造与拷贝构造

在这里插入图片描述

常见的构造有:

vector<int> v1;
vector<int> v2(10,1);
vector<int> v3(v2);

v2:构造并初始化10个值为1的顺序表

vector可以用迭代器区间初始化:

string str("abcdefg");
vector<string> vv(str.begin(),str.end());

2.2 vector迭代器的使用

在这里插入图片描述
和string一样,vector有正向和反向
两种迭代器,且使用方法和string相同

在这里插入图片描述

vector<int> vv{1,2,3,4,5,6};
vector<int>::iterator it = vv.begin();
while(it!=vv.end())
{
	cout<<*it;
	it++;
}

2.3 vector空间相关函数

在这里插入图片描述

vector的空间相关的函数
和string的机会一模一样
如果你看了文档还不懂的话
可以先阅读此篇文章:string接口函数


2.4 vector的增删查改

在这里插入图片描述
push_back和pop_back
都是老朋友了,这里就不多说了
在介绍insert和erase之前
先来了解几个算法库的函数


2.41 find,swap和sort

这三个函数都在头文件:algorithm

在这里插入图片描述

find函数:参数是一段迭代器区间
以及在此区间你需要查找的值
找到后返回这个值对应的迭代器位置
若找不到,则返回迭代器last

find的使用:

vector<int> vv{1,2,3,4,5,6,7,8,9};
auto pos = find(vv.begin(),vv.end(),5);
cout<<*pos;

注:使用auto是为了简写迭代器也可以用
vector< int >::iterator替代

在这里插入图片描述

swap想必是大家的常客了
这里给它个面子,就不介绍它了

在这里插入图片描述

sort非常方便,它内部实现是快排
我们只需要传一个迭代器区间
就可以将整个区间排好序

sort的使用:

vector<int> vv{5,7,3,9,6,4,1,2,8};
sort(vv.begin().vv.end());

2.42 insert和erase

在这里插入图片描述

和string不同,vector的insert
的参数pos不是整型,而是迭代器
默认是在pos位置前插入一个数据

insert和find常常配合在一起使用

在整型5前面插入一个100:

vector<int> vv{1,2,3,4,5,6,7,8,9};
auto pos = find(vv.begin(),vv.end(),5);
vv.insert(pos,100);

在这里插入图片描述

和string的erase不同,vector
的erase一次只删除一个数据
然而string如果使用缺省值就是
将全部数据删完

vector的erase甚至可以删除一段区间

删除顺序表中值为100的元素

vector<int> vv{1,2,3,4,5,6,7,8,9,100};
auto pos = find(vv.begin(),vv.end(),100);
vv.erase(pos);
//删除一个区间
vv.erase(vv.begin()+2,vv.end()-2);

2.43 随机访问operator[ ]

vector中最喜欢用的是[ ]
它支持随机访问,是否方便

operator[]的使用:

vector<int> vv{1,2,3,4,5,6,7,8,9};
for(int i=0;i<vv.size();i++)
{
	cout<<vv[i]<<" ";
}

3. vector的模拟实现

首先要关注的是成员变量
vector是顺序表,所以和实现C语言
时的顺序表一样,至少有三个参数

  1. 指向一段空间的指针
  2. 空间的有效大小
  3. 空间的实际大小

由于vector的迭代器就是普通指针
所以成员变量的类型其实是迭代器

template<class T>
class vector
{
public:
	typedef T* iterator;

private:
	iterator _start;
	iterator _finish;
	iterator _endof_storage;

这里使用迭代器作为三个参数的类型
是因为:求vector的size和capacity时
可以直接使用finish-start
也就是指针相减求出长度

成员变量和空间的关系:

在这里插入图片描述


3.1 vector容量相关函数

上来首先要考虑的容量相关的函数:

  • size
  • capacity
  • empty
  • resize
  • reverse

前三个十分简单:

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

size_t capacity() const
{
	return _endof_storage - _finish;
}

bool empty() const
{
	return (size()==0);
}

3.11 reverse函数

reverse只会改变capacity的大小
并不会改变size的大小

void reserve(size_t n)
{
	if (n > capacity())
	{
		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;
		_end_of_storage = _start + n;
	}
}

注:当n小于capacity时,不进行扩容

由于C++内存管理的new
无法像C语言的realloc一样原地扩容
所以必须先开辟n个空间,再将数据
拷贝到新空间,且释放旧空间


3.12 resize函数

resize即会改变size大小
也会改变capacity大小

resize要分三种情况:

  1. n大于capacity时
  2. n大于size小于capacity时
  3. n小于size时

它们的解决方案分别是:

  • 直接套用reversezhu

  • 初始有效值不变,在此之后
    初始化新的内容

  • 直接将size缩小到n

void resize(size_t n, const T& val = T())
{
	if (n > capacity())
	{
		reserve(n);
	}

	if (n > size())
	{
		// 初始化填值
		while (_finish < _start + n)
		{
			*_finish = val;
			++_finish;
		}
	}
	else
	{
		_finish = _start + n;
	}
}

注:参数val=T()使用了匿名对象
C++将内置类型特殊处理过
int/char等等都被升级为了类
所以可以使用int()表示匿名对象

int tmp1 = int();
int tmp2 = int(10);

int的缺省值为0


3.2 vector的构造函数

  1. 首先最简单的无参构造:
vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}
  1. 紧接着是带参的构造函数
    我们跟着STL库的风格走:
vector(size_t n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(n);//开辟n个空间
	for (size_t i = 0; i < n; ++i)
	{
		push_back(val);//给初始值赋值
	}
}
  1. 最后是使用迭代器区间来构造
    比如我想在顺序表中存放string类型:
string str("abcdefg");
vector<string> vv(str.begin(),str.end());

此时在模板类中还应该有一个模板

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

注:inputiterator取名是模仿STL的
你也可以取任一除了T的名字


3.3 vector的析构函数

vector的析构函数非常简单
只需要将空间释放
并且将各个指针置为空就行了

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

3.4 vector的拷贝构造函数

拷贝构造的实现有很多种写法
大家可以先自己尝试一下

vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _endof_storage(nullptr)
	{
		reserve(v.size());
		for (const auto& e : v)
		{
			push_back(e);
		}
	}

4. 总结以及拓展

vector模拟实现的全部代码我将在
下一篇文章中分享给大家

可以发现:STL的神奇之处在于
它把所有接口函数都做了统一化处理
每一个容器的接口函数的使用都相似
但是内部实现被这种封装隐藏起来了
进一步又体现了C++的三大特性:
封装

并且C++实现了所有容器通用的算法库
比如sort和find都只需要传迭代器
然而所有容器都会被迭代器封装
所以一份代码就能实现对不同容器的操作

在这里插入图片描述

拓展题目:

熟悉了vector的基本使用
可以尝试解决一下下面几个问题:

  • 只出现一次的数字
  • 删除有序数组中的重复项
  • 数组中出现次数超过一半的数字
  • 杨辉三角

留给大家当作小试牛刀了~


🔎 下期预告:迭代器失效和深浅拷贝问题 🔍

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

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

相关文章

无涯教程-Python机器学习 - Reinforcement Learning函数

这些方法不同于以前研究的方法,也很少使用。在这种学习算法中,我们需要在一段时间内训练一个代理,以便它可以与特定环境交互。代理将遵循一系列与环境进行交互的策略,然后在观察环境之后,它将针对环境的当前状态采取措施。以下是强化学习方法的主要步骤。 第1步-首先,我们需要准…

金鸣表格文字识别软件,让你的图片瞬间变成excel

来百度APP畅享高清图片 首先&#xff0c;让我们打开金鸣表格文字识别软件&#xff01; 然后点击那个“添加文件”的按钮&#xff0c;在弹出的窗口中选择你想要识别的图片&#xff0c;再点击“打开”&#xff0c;就可以把图片添加到待识别的列表中了。 接下来&#xff0c;你只需…

领星ERP和金蝶云星空接口打通对接实战

领星ERP和金蝶云星空接口打通对接实战 对接系统&#xff1a;领星ERP 深圳市领星网络科技有限公司创立于2017年&#xff0c;致力于通过SaaSERP产品为跨境电商行业创造价值&#xff0c;让跨境生意更简单。公司总部位于深圳&#xff0c;在广州、杭州、厦门等设有服务中心。领星现已…

[计算机入门] 账户管理

3.4 账户管理 用户账户是计算机操作系统中用于标识和管理用户身份的概念。 每个用户都拥有一个唯一的用户账户&#xff0c;该账户包含用户的登录名、密码和其他与用户身份相关的信息。 用户账户通常用于验证用户身份&#xff0c;并授权对系统资源的访问权限。在多用户操作系统…

SSL证书申请

DV SSL证书申请需要多久&#xff1f; DV SSL证书无需验证所有者资质资料&#xff0c;审核流程相对简单&#xff0c;因此可快速签发。但部分域名信息可能会触发不同等级的安全审查机制&#xff0c;必要时需要人工介入进行审查签发&#xff0c;因此&#xff0c;SSL证书签发时间可…

【OpenCV • c++】图像对比度调整 | 图像亮度调整

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

GIS全国技能大赛试题及解题过程

1、提供数据列表如下&#xff1a; 2、试题要求如下&#xff1a; 3、解题步骤如下&#xff1a; &#xff08;1.1&#xff09;导入土地利用数据&#xff0c;如下&#xff1a; &#xff08;1.2&#xff09;导入土地采集表格&#xff0c;然后右键选择显示XY数据&#xff0c;如下&am…

python二维索引转一维索引 多维索引转一维索引

将二维索引转为1维索引 原博客地址&#xff1a;https://blog.csdn.net/qq_42424677/article/details/123011642 将n维索引映射成1维索引 def ravel_index(x, dims):i 0for dim, j in zip(dims, x):i * dimi jreturn i

Cesium 叠加天地图-中国近海海洋等深面图层服务

Cesium 叠加天地图-中国近海海洋等深面图层服务 核心代码完整代码&#xff1a;在线示例 偶然发现天地图有一个近海海洋图层&#xff0c;觉得不错&#xff0c;于是尝试叠加一下&#xff0c;花费了一些时间&#xff0c;叠加成功&#xff0c;这里分享一下。 本文包括核心代码、完…

Google Zxing依赖在linux服务器上生成二维码图片中带有中文显示不了的问题。

一&#xff0c;问题描述 在二维码中显示的图片中含有中文&#xff0c;不显示而是显示乱码。这是因为linux系统中为安装中文。 二&#xff0c;解决方法 1、查看所有字体&#xff1a;fc-list // 如果提示 fc-list: command not found&#xff0c;则需要安装# yum install font…

智慧排水监测系统:提高城市排水管理效率

随着城市化进程的不断推进&#xff0c;城市排水系统在城市正常运行和居民生活品质方面扮演着至关重要的角色。然而&#xff0c;随着城市化进程的加速和气候变化的加剧&#xff0c;城市排水系统面临前所未有的挑战&#xff0c;城市内涝、雨污分流不到位、河道黑臭杂乱、水体污染…

c语言练习题36:删除指定的数

删除指定的数 题目&#xff1a; 先输⼊5个整数存放在数组中&#xff0c;再输⼊⼀个整数n&#xff0c;删除数组中所有等于n的数字&#xff0c;数组中剩余的数 组保证数组的最前⾯&#xff0c;打印剩余的数字。 思路&#xff1a; 使⽤两个指针 i 和 j 。 1. i 从前往后扫描整…

网络服务第三次作业

正向解析 1.关闭服务端与客户端防火墙和SElinux 2.修改服务端与客户端的IP为静态IP地址 3.安装DNS软件 服务端IP客户端IP 网址 192.168.50.128192.168.50.131www.openlab.com. ##服务端&#xff1a; [rootquantou ~]# setenforce 0 ##关闭SELinux [rootquantou ~]# syste…

苹果通讯录怎么导入新手机?换了新手机的朋友请看这里

通讯录联系人、照片、视频和文件都是苹果手机中非常重要的数据。当人们更换手机时&#xff0c;照片、视频等文件可以通过“微信发送”或者“隔空投送”一键传输到新手机。 那么&#xff0c;苹果通讯录怎么导入新手机呢&#xff1f;小编给大家总结了2个简单转移通讯录的方法&am…

静电接地桩方案设计和施工

静电接地桩是确保设备、建筑物或工业场所与地面之间能够良好地导电的重要措施之一。以下是一般的静电接地桩方案设计和施工步骤&#xff1a; 1. 设计&#xff1a;首先需要确定需要进行静电接地的设备或建筑物的类型、结构和规模。根据相关的标准和规范&#xff0c;计算出所需的…

②matlab桌面和编辑器

目录 matlab编辑器练习 运行脚本 matlab编辑器练习 您可以通过点击灰色代码框在脚本中输入命令。 准备就绪后&#xff0c;您可以通过点击蓝色的提交按钮提交代码。 任务 在脚本中输入命令 r 3。 2.任务 在脚本中添加命令 x pi*r^2。 附加练习 当您在实时编辑器中完成…

OLED透明屏单价:了解影响因素及市场趋势

在当今科技发展迅猛的时代&#xff0c;OLED透明屏作为一种创新的显示技术&#xff0c;已经广泛应用于各个行业。 而了解OLED透明屏的单价以及影响因素对于购买和使用者来说至关重要&#xff0c;那么尼伽将深入探讨OLED透明屏单价的相关知识&#xff0c;希望大家看后能有所收获…

f4v如何格式转换mp4格式?分享几种好用转换方法

为了使视频文件格式更加通用&#xff0c;更容易在不同设备和平台上播放&#xff0c;需要将F4V格式转换为MP4格式。F4V是Adobe Flash Player使用的一种视频文件格式&#xff0c;而MP4格式是一种更通用的视频文件格式&#xff0c;几乎所有设备和平台都支持它。此外&#xff0c;MP…

RocketMQ mqadmin java springboot python 调用笔记

命令 mqadmin命令列表 yeqiangyeqiang-MS-7B23:/opt/rocketmq-all-5.1.3-bin-release$ sh bin/mqadmin The most commonly used mqadmin commands are:updateTopic Update or create topicdeleteTopic Delete topic from broker and NameServer.…

免费数据恢复软件推荐,5步快速恢复数据!

“我是一名学生&#xff0c;前几天把小组汇报资料保存在电脑里&#xff0c;但是不知道为什么这个汇报文件丢失了&#xff0c;请问大家有什么免费的数据恢复软件可以帮我恢复这个文件吗&#xff1f;非常着急&#xff01;” 数据丢失是每个电脑用户都可能面临的问题。无论是因为误…