Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++进阶】深入STL之vector:构建高效C++程序的基石

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

作者头像
Eternity._
发布于 2024-06-14 11:47:31
发布于 2024-06-14 11:47:31
23800
代码可运行
举报
文章被收录于专栏:登神长阶登神长阶
运行总次数:0
代码可运行

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

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

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


📒1.vector类的基本概念

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


vector类成员函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);

使用迭代器进行初始化构造

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的成员接口

代码示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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搭配使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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之前,我们创建一个属于自己的命名空间来与库里面的区分

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的构造函数

无参构造:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}

带参的构造函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的模拟实现下面会讲
	}
}

迭代器区间构造

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的析构函数

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
~vector()
{
	delete[] _start;
	_start = _finish = _end_of_storage = nullptr;
}

🌻vector的拷贝构造函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _endof_storage(nullptr)
	{
		reserve(v.capacity());
		for (const auto& e : v)
		{
			push_back(e);
		}
	}

🌼vector的运算符重载

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的大小

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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大小

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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()表示匿名对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main()
{
	cout << int() << endl; // int的缺省值为0,所以输出 0
	return 0;
}

push_back

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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还是其他任何技术,都值得我们不断学习和探索。让我们保持对知识的渴望和好奇心,不断前行,在编程的道路上越走越远 谢谢大家支持本篇到这里就结束了,祝大家天天开心!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++】STL--vector
使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习
用户11375356
2024/11/22
910
【C++】STL--vector
【C++/STL】vector的底层刨析和模拟实现
✨这里将vector的实现都放在一个头文件下,放置多个文件可能会出现链接错误;并设置自己的命名空间,比如我这设置的就是 qian
IsLand1314
2024/10/15
1720
【C++/STL】vector的底层刨析和模拟实现
【深入探索 C++ STL 容器 vector】 —— 随机访问与高效存储的完美融合
https://blog.csdn.net/bite_zwy/category_12852141.html
换一颗红豆
2024/12/20
1980
【深入探索 C++ STL 容器 vector】 —— 随机访问与高效存储的完美融合
【C++】vector的模拟实现
通过观察函数的实现过程,可以得知 start与begin等价 ,end与finish等价
lovevivi
2023/04/28
3960
【C++】vector的模拟实现
库中如何实现vector
本应该开空间,然后再将数据插入进容器vector,此处我们复用resize函数的一种.就不需要自己再手撕一遍了.
初阶牛
2023/10/14
1830
库中如何实现vector
【C++】vector及模拟实现
为了方便打印vector中不同类型的数据,可以将迭代器遍历和范围for遍历封装成一个模版函数,有几点需要注意:
_小羊_
2024/10/16
870
【C++】vector及模拟实现
【C++】STL——vector 深度剖析 及 模拟实现
其实大家可以认为vector就是我们之前数据结构学的顺序表,那说到顺序表,相信就不用给大家过多解释了。
YIN_尹
2024/01/23
3100
【C++】STL——vector 深度剖析 及 模拟实现
C++:Vector的模拟实现
       在学习string类的时候,我们可能会发现遍历的话下标访问特别香,比迭代器用的舒服,但是下标其实只能是支持连续的空间,他的使用是非常具有局限性的,随着STL学习的深入我们会发现其实迭代器才是大佬!!Vector虽然也支持下标访问,但是很多成员函数都是用的迭代器,所以我们要模拟实现的话迭代器十分重要,vs使用的是PJ版的STL版本,比较难懂,所以我们模拟实现统一用SGI版本去实现,所以在模拟实现之前,我们要去看看他的源码到底有哪些成员变量
小陈在拼命
2024/03/08
1200
C++:Vector的模拟实现
【C++】深入探索:从零开始模拟实现C++中的Vector容器
在C++中,vector是一个非常常用的容器,它提供了一种动态数组的实现方式,允许我们在运行时动态地增加或减少元素的数量。vector的内部实现主要依赖于动态分配的内存和连续存储的元素。
P_M_P
2024/07/30
1770
【C++】深入探索:从零开始模拟实现C++中的Vector容器
C++ —— vector 的模拟实现
https://blog.csdn.net/hedhjd/article/details/142334349?spm=1001.2014.3001.5501
迷迭所归处
2024/11/19
910
C++ —— vector 的模拟实现
【C++】简化源码——vector的模拟实现
这本质上与T*a,size_t size,size_t capacity是类似的:
平凡的人1
2023/10/15
2030
【C++】简化源码——vector的模拟实现
【c++丨STL】vector模拟实现
本篇文章,我们将深入探讨vector的底层实现原理,并尝试模拟实现其结构以及一些常用接口。
ephemerals__
2024/11/13
1040
【c++丨STL】vector模拟实现
【C++】vector的模拟实现(SGI版本)
1. 下面是vector的框架,其中成员变量分别为指向当前使用空间首部分的_start指针和最后一个元素的下一个位置的_finish指针,以及指向可用空间末尾的下一个位置的_end_of_storage指针,并且对于vector来说,由于它的底层是由顺序表实现的,所以它的迭代器就是原生态指针T*,我们定义了const和非const的迭代器,便于const和非const对象的迭代器的调用。
举杯邀明月
2023/04/12
6030
【C++】vector的模拟实现(SGI版本)
C++ STL学习之【vector的模拟实现】
vector 是 STL 中的容器之一,其使用方法类似于数据结构中的 顺序表,得益于范型编程和 C++ 特性的加持,vector 更强大、更全能;在模拟实现 vector 时,还需要注意许多细枝末节,否则就很容易造成重复析构及越界访问
北 海
2023/07/01
2800
C++ STL学习之【vector的模拟实现】
初识C++ · 模拟实现vector
继上文模拟实现了string之后,接着就模拟实现vector,因为有了使用string的基础之后,vector的使用就易如反掌了,所以这里直接就模拟实现了,那么实现之前,我们先看一下源代码和文档:
_lazy
2024/10/16
950
初识C++ · 模拟实现vector
【C++】Vector的简易模拟与探索
此外范围for其实质上就是通过迭代器来实现的,所以我们写完了迭代器就可以使用范围for来遍历数据了,代码如下:
大耳朵土土垚
2024/05/28
1060
【C++】Vector的简易模拟与探索
vector介绍与使用【C++】
C++中的vector是一个动态数组,它可以根据需要自动调整大小。它存储在连续的内存块中,提供了快速的随机访问和插入操作,但删除操作可能导致内存的移动。vector是STL(标准模板库)的一部分,可以容纳任何类型的元素,包括内置类型和用户定义的类型。使用vector时,需要包含头文件,并通过std命名空间访问。vector还提供了许多成员函数,如push_back()、pop_back()、size()等,以支持各种操作。
鲜于言悠
2024/05/10
2100
vector介绍与使用【C++】
【探索 C++ Vector】数据存储利器,动态扩容随心控。高效管理数据序列,从简单元素排列到复杂结构构建皆能胜任。助力开发者轻松应对多变数据需求,开启便捷高效的 C++ 数据处理新征程。
vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中 我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。
逆向-落叶
2024/12/25
860
【探索 C++ Vector】数据存储利器,动态扩容随心控。高效管理数据序列,从简单元素排列到复杂结构构建皆能胜任。助力开发者轻松应对多变数据需求,开启便捷高效的 C++ 数据处理新征程。
C++:手把手教你手撕vector
vector.hpp是源文件里面是vector的实现,main函数是测试用的,因为一个项目只能有一个main入口对吧;
啊QQQQQ
2025/02/20
1100
C++:手把手教你手撕vector
C++奇迹之旅:手写vector模拟实现与你探索vector 容器的核心机制与使用技巧
我们先定义自己的命名空间俩封装自定义的vector类,这样可以避免与标准库中的 vector 发生命名冲突。随即,我们定义模版类vector,三个成员变量都是迭代器,而vector迭代器又是原生指针,所以我们将指针取别名为iterator
学习起来吧
2024/08/29
2020
C++奇迹之旅:手写vector模拟实现与你探索vector 容器的核心机制与使用技巧
推荐阅读
相关推荐
【C++】STL--vector
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验