【C++进阶】深入STL之vector:构建高效C++程序的基石

📝个人主页🌹:Eternity._
⏩收录专栏⏪:C++ “ 登神长阶 ”
🤡往期回顾🤡:模拟实现string
🌹🌹期待您的关注 🌹🌹

在这里插入图片描述

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

❀STL之vector

  • 📒1.vector类的基本概念
  • 📕2. vector类的常用操作
    • 🌈vector类对象的常见构造
    • 🌞vector类对象的容量操作
    • 🌙vector类对象的增删查改
  • 📜3. vector类的模拟实现
    • 🍁vector的成员变量
    • 🌸vector的构造函数
    • 🌷vector的析构函数
    • 🌻vector的拷贝构造函数
    • 🌼vector的运算符重载
    • 🍂vector容量相关函数
  • 📖4. 总结


学习STL中的vector:开启C++容器之旅的前言

  • 在C++的编程世界中,标准模板库(STL)无疑是每位开发者都需要熟练掌握的工具集。其中,vector作为STL中最常用的动态数组容器之一,以其灵活、高效和易用的特性,成为了众多C++程序员的首选。

vector容器允许我们存储任意数量的同类型元素,并且能够根据需要进行动态扩展。这种灵活性使得vector在处理大量数据时变得尤为高效,无论是在科学计算、图形处理、网络编程还是游戏开发等领域,我们都能看到vector的身影。
现在让我们一起踏上学习STL中vector的旅程吧!


📒1.vector类的基本概念

vector是C++标准模板库(STL)中的一个动态数组容器,它提供了对一段连续空间的动态管理功能。与普通的C++数组相比,vector具有许多优点,如可以动态调整大小、支持随机访问等

在这里插入图片描述


vector类成员函数:

class string
{
private:
	iterator _start;
	iterator _finish;
	iterator _end_of_storage;
};

在这里插入图片描述


📕2. vector类的常用操作

🌈vector类对象的常见构造

构造函数声明接口说明
vector()无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x);拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造
int main()
{
	vector<int> v1; // 无参构造
	vector<int> v2(10, 0); // 构造并初始化n个val
	vector<int> v3(v2); // 拷贝构造
	vector<int> v4(v2.begin(),v2.end()); // 使用迭代器进行初始化构造
	return 0;
}

关于 vector iterator 的使用

iterator的使用接口说明
begin +end获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

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

其实vector的很多用法和string类似


🌞vector类对象的容量操作

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity
int main()
{
	vector<int> v(10, 0);
	cout << v.size() << endl; // 获取数据个数
	cout << v.capacity() << endl; // 获取容量大小

	v.reserve(20); // 改变vector的capacity
	cout << endl;
	cout << "after reserve size: " << v.size() << endl;
	cout << "after reserve capacity: " << v.capacity() << endl;
	
	cout << endl;
	
	v.resize(20); // 改变vector的size
	cout << "after resize size: " << v.size() << endl;
	cout << "after resize capacity: " << v.capacity() << endl;

	cout << v.empty() << endl; // 判断是否为空
	return 0;
}

在这里插入图片描述

注意:

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL
  • reserve只负责开辟空间,不会影响size的大小,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,会影响size的大小

🌙vector类对象的增删查改

vector增删查改接口说明
push_back尾插
pop_back尾删
insert在pos之前插入val
erase删除pos位置的数据
swap交换两个vector的数据空间
operator[ ]像数组一样访问

注意:find 查找,这个是算法模块实现,不是vector的成员接口
在这里插入图片描述

代码示例:

int main()
{
	vector<int> v1(1, 0);
	v1.push_back(1); // 尾插
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(5); // 尾插后v1 : 0,1,2,3,5

	v1.pop_back(); // 尾删后v1 : 0,1,2,3

	cout << "v1: ";
	for (size_t i = 0; i < v1.size(); i++) // 遍历vector数组
	{
		cout << v1[i] << " "; // operator[]随机访问
	}
	cout << endl;

	vector<int> v2(10, 0);
	cout << "v2: ";
	for (size_t i = 0; i < v2.size(); i++)
	{
		cout << v2[i] << " ";
	}
	cout << endl;
	
	v1.swap(v2); // 交换v1,v2内容
	cout << "after swap v1: ";
	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	vector<int>::iterator it = find(v1.begin(), v1.end(), 0); // 查找
	cout << *it;
	return 0;
}

在这里插入图片描述


注意:insert和erase在vector里面有点特殊,在vector上它使用的都是迭代器

在这里插入图片描述

erase往往和find搭配使用

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

//删除一个区间
v.erase(v.begin() + 1,v.end() - 1);

在这里插入图片描述

insert头插一个0

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

📜3. vector类的模拟实现

🍁vector的成员变量

首先我们要先搞清楚 vector的成员变量,我们清楚 vector类在底层实际上也是指针,在模拟实现 vector之前,我们创建一个属于自己的命名空间来与库里面的区分

namespace pxt
{
	template<class T>
	class vector
	{
	public:
		// vector的迭代器是一个原生指针
		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;
		}
	private:
		// 成员变量
		iterator _start; // 指向有效数据的头
		iterator _finish; // 指向有效数据的尾
		iterator _end_of_storage; // 指向最大空间的地方
	};
}

在这里插入图片描述

在这里插入图片描述


🌸vector的构造函数

无参构造:

vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}

带参的构造函数

vector(size_t n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(n); // 开辟空间
	for (size_t i = 0; i < n; i++)
	{
		push_back(val); // 给初始值赋值
		// reserve,push_back的模拟实现下面会讲
	}
}

迭代器区间构造

为了实现不同类型迭代器的构造,这里需要再创建一个模板

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

🌷vector的析构函数

析构函数比较简单,将空间释放,各个指针置为空

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

🌻vector的拷贝构造函数

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

🌼vector的运算符重载

void swap(vector<T> v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_end_of_storage, v._end_of_storage);
}
// 现代写法
vector<T>& operator=(vector<T> tmp)
	{
		swap(tmp); 
		return *this;
	}

🍂vector容量相关函数

跟容量有关的函数size,capacity,empty,resize,reverse,push_back

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

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

bool empty() const
{
	return _start == _finish;
}

reverse

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

void reserve(size_t n)
{
	if (n > capacity()) // n < capacity()时,则不需要作出反应
	{
		size_t sz = size(); // 先保存以下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;
	}
}

resize

resize不仅会改变size大小,也会改变capacity大小

void resize(size_t n, const T& val = T()) // val=T()用了匿名对象
{
	if (n > capacity())
	{
		reserve(n); // 开辟额外空间
	} 

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

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

int main()
{
	cout << int() << endl; // int的缺省值为0,所以输出 0
	return 0;
}

push_back

void push_back(const T& x)
{
	if(_finish == _end_of_storage)
	{
		size_t sz = size();
		size_t cp = capacity() == 0 ? 4 : capacity() * 2;
		T* tmp = new <T>(cp);
		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 + cp;
	}
	*_finish = x;
	_finish++;
}

当探索并深入了解了STL中的vector容器后,我们不禁感叹其强大的功能和灵活性。随着对vector的学习和使用,我们逐渐理解到,一个高效的C++程序不仅仅是代码的堆砌,更是对数据结构、算法和STL等标准库深刻理解的体现。vector的迭代器、容量管理、元素访问以及算法支持等功能,都是我们在日常编程中不可或缺的工具


📖4. 总结

学习vector仅仅是开始。STL(Standard Template Library)还提供了诸如list、set、map等其他强大的容器,每个都有其独特的特点和适用场景。因此,鼓励大家继续深入学习STL,探索其背后的设计理念和实现原理。通过不断实践,我们不仅能够提高编程效率,还能够培养出更加优雅、健壮的代码风格。最后,我想说的是,学习是一个永无止境的过程。无论是STL还是其他任何技术,都值得我们不断学习和探索。让我们保持对知识的渴望和好奇心,不断前行,在编程的道路上越走越远

在这里插入图片描述
谢谢大家支持本篇到这里就结束了,祝大家天天开心!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NLP基础——序列模型(动手学深度学习)

序列模型 定义 序列模型是自然语言处理&#xff08;NLP&#xff09;和机器学习领域中一类重要的模型&#xff0c;它们特别适合处理具有时间顺序或序列结构的数据&#xff0c;例如文本、语音信号或时间序列数据。 举个例子&#xff1a;一部电影的评分在不同时间段的评分可能是…

【个数】滑动窗口-1004. 最大连续1的个数 III 1493. 删掉一个元素以后全为 1 的最长子数组

题目链接及描述 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目分析 今日写到这个题目&#xff0c;是滑动窗口的标签&#xff0c;但首先看到后感觉和之前做过的滑动窗口题目有点区别&#xff0c;之前滑动窗口通过给定一个区间长度&#xff0c;随后区…

.NET集成DeveloperSharp实现图片的裁剪、缩放、与加水印

&#x1f3c6;作者&#xff1a;科技、互联网行业优质创作者 &#x1f3c6;专注领域&#xff1a;.Net技术、软件架构、人工智能、数字化转型、DeveloperSharp、微服务、工业互联网、智能制造 &#x1f3c6;欢迎关注我&#xff08;Net数字智慧化基地&#xff09;&#xff0c;里面…

第一篇 逻辑门(与门、或门、非门、异或门)

一、实验目的 了解DE1-SOC开发板一些外设。 掌握常用组合逻辑门电路的基本原理。 学习Verilog HDL的基本语法。 学习使用ModelSim工具对设计的电路进行仿真&#xff0c;包括编写Testbench仿真代码&#xff0c;以及ModelSim工具的使用。 熟悉使用Quartus软件从创建Quartus工…

el-tooltip使用记录

记录工作中使用el-toolitp的情况 需求一&#xff1a;列表项内容超出限制时&#xff0c;点击单元格展示Tooltip 需求描述&#xff1a;某列表项内容返回过多&#xff0c;超出最大限制时&#xff1a; 1.点击该单元格再显示tooltip&#xff1b; 2.点击下一行更新tooltip内容&…

《数字图像处理-OpenCV/Python》第15章:图像分割

《数字图像处理-OpenCV/Python》第15章&#xff1a;图像分割 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第15章&#xff1a;图像分割 图像分割是由图像处理到图像分析的关键步骤…

关于gitee上传成功没有绿点

今天上传完代码以后&#xff0c;打开gitee看了一下&#xff0c;但是看到昨天和今天都没有小绿点&#xff0c;仔细思考了一番&#xff0c;是仓库满了&#xff1f;不对啊&#xff0c;如果满了的话&#xff0c;上传就会失败啊&#xff0c;那这是什么问题呢&#xff1f; 原来是因为…

Parallels Desktop for Mac 19.4.0更新了哪些内容?有什么改进?

带来了重新设计的共享 Mac 文件夹版本&#xff0c;这些文件夹现在是符号链接&#xff0c;像指针一样指向您的 Mac 文件夹中的文件&#xff0c;同时仍然显示在 Windows 的本地磁盘上。 修复了由于共享文件夹问题导致 NinjaTrader 无法正常启动的问题。 修复了由于共享文件夹问…

2024中国跨境电商海外营销观察报告

来源&#xff1a;霞光智库 近期历史回顾&#xff1a;战略测量的未来报告 2024影响力系列白皮书&#xff08;第五册&#xff09;——绿氢 2024年Z世代与千禧一代调研报告.pdf 2023中国车规级芯片产业白皮书.pdf 2024全球网文应用营销洞察报告.pdf 2024年Q1抖音女性卫生用品行业趋…

操作系统教材第6版——个人笔记1

第一章 计算机操作系统概述 操作系统是计算机系统中最重要的系统软件&#xff0c;它统一管理计算机系统的硬件资源与信息资源&#xff0c;控制与调度上层软件的执行并为其提供易于使用的接口。从资源管理、程序控制、操作控制、人机交互、程序接口、系统结构6个角度深入观察操…

JS冒泡排序案例详解

先看一下案例效果&#xff1a; HTML代码&#xff1a; <input type"text" value"" id"bubble-input"> <button onclick"bubbleSort()">冒泡排序</button> <h4 id"bubbleSort-result"></h4>J…

vue2 bug求助!!!(未解决,大概是浏览器缓存的问题或者是路由的问题)

我的vue2项目出现了一个超级恶心的bug 过程&#xff1a; 1 操作流程&#xff1a;页面a点击a标签->到页面b->页面b用户退出刷新页面->点击浏览器的返回按钮返回上一页 2 结果&#xff1a;返回页面后页面没有刷新导致用户名还显示着&#xff0c;页面没有发生任何变化&a…

5.3.2网安学习第五阶段第三周回顾(个人学习记录使用)

本周重点 ①网络安全攻防技术体系 ②Windows入侵排查 ③Linux入侵排查 ④僵蠕木毒排查与处理 本周主要内容 ①网络安全攻防技术体系 一、攻击层面 1、分类 &#xff08;1&#xff09;指定目标&#xff1a;APT攻击手段&#xff0c;对指定目标进行长期作战和渗透&#x…

从Multisim到Proteus,再到SmartEDA:电子设计软件的进化之旅

在电子设计领域&#xff0c;软件工具的演进犹如一条璀璨的轨迹&#xff0c;记录着科技进步的每一个步伐。从Multisim的初创&#xff0c;到Proteus的崛起&#xff0c;再到如今SmartEDA的崭露头角&#xff0c;这些电子设计软件不仅极大地提升了设计效率&#xff0c;更推动了整个行…

函数高级:函数的默认参数|函数的占位参数|函数重载

函数的默认参数 函数占位参数 函数重载 总结&#xff1a; 函数的形参&#xff0c;有自己的参数值就用参数值&#xff0c;没有就用形参列表的默认值。 参数列表中&#xff0c;某位置有自己的默认值&#xff0c;从该位置起&#xff0c;往后就都必须设有默认值。 函数声明和函数…

一键设置常用纸张和页面边距-Word插件-大珩助手

Word大珩助手是一款功能丰富的Office Word插件&#xff0c;旨在提高用户在处理文档时的效率。它具有多种实用的功能&#xff0c;能够帮助用户轻松修改、优化和管理Word文件&#xff0c;从而打造出专业而精美的文档。 【新功能】常用纸张和常用边距 1、一键设定符合中国人常用…

器利而事善——datagrip 的安装以及连接mysql

一&#xff0c;安装 下载&#xff1a;直接到官网下载即可&#xff0c; 破解&#xff1a;这是破解连接&#xff1a;https://pan.baidu.com/s/11BgOMp4Z9ddBrXwCVhwBng &#xff0c;提取码&#xff1a;abcd&#xff1b; 下载后&#xff0c;选择倒数第三个文件&#xff0c;打开da…

ant design vue 表格错位,表头错位

ant design vue 表格错位,表头错位 在官网中,我们可以看到下面图片的描述: 好的,我们按照官网来一波,前面都设置了固定宽度,娃哈哈就不设置了.会出现下面效果 为啥会多了一个竖线(因为按照官网来一波x:1300,这个1300太小的原因) 3.那我们把1300改成1600,1700试试,结果也不是…

揭秘大数据时代的数据库存储引擎:关系型、NoSQL与NewSQL如何选择?

文章目录 01 关系型数据库&NoSQL数据库&NewSQL数据库1. 关系型数据库2. NoSQL数据库3. NewSQL数据库 02 OLTP&OLAP&HTAP对比1. OLTP数据库2. OLAP数据库3. HTAP数据库 03 总结 在大数据和AI时代&#xff0c;数据库成为各类应用不可或缺的重要组成部分。而数据库…

机器学习AI大模型的开源与闭源:哪个更好?

文章目录 前言一、开源AI模型1.1 开源的优点1.2 开源的缺点 二、闭源AI模型2.1 闭源的优点2.2 闭源的缺点 三、开源与闭源的平衡3.1 开源与闭源结合的案例3.2 开源与闭源的战略选择 小结 前言 在过去的几年里&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xf…