当前位置: 首页 > article >正文

【C++】STL标准库之vector

STL标准库之vector

  • vector类的简介
  • 常用的vector类的接口
    • 构造
    • 容量
    • 遍历及访问
    • 增删查改
    • 迭代器
    • 迭代器失效问题

vector类的简介

vector是大小可变数组的序列容器,与string相比,vector中可以存任何类型的数据,而string中存储的只能是字符类型。
因为vector采用的是连续存储空间,因此它也可以通过下标对vector中的元素进行访问,而它比数组的优势在于,它的大小是可以动态改变的,它的大小会被容器自动处理。
在插入新元素的时候,并没有使用常规的开辟新数组,拷贝元素,释放旧空间,而是会以空间换取时间的方式,事先多分配一部分空间,以便于未来可能会增加的元素

常用的vector类的接口

构造

函数名称功能
vector()无参构造
vector(size_t n, const value_t& val = val_type())构造并初始化n个val
vector(const vector& v)拷贝构造
vector(InputIterator first, InputIterator last)使用迭代器进行构造

对应写法

vector<int> v();
vector<int> v1(5, 10);
vector<int> v2(v);
vector<int> v3(v1.begin(), v1.begin()+5);

注意:vector是一个类模板,需要在构造时进行类型定义。
而在c++11中,还可以用数组直接进行构造 vector v(1,2,3,4,5);

容量

函数名称功能
size获取元素个数
capacity获取当前容量大小
empty判断当前vector是否为空
resize改变vector中有效元素的个数
reserve改变容量大小(只增不减)

当前的容量部分的函数实际上和string的非常相似,但是string在resize中由于内部存在的数组,与vector稍微不同
我们在扩容时,vs下是以1.5倍来扩容的,g++是按2倍来扩容的。如果事先知道vector中大概要存放多少个元素,可以先对其进行扩容,这样就能够避免边插入边扩容的问题了。

遍历及访问

函数名称功能
operator[]访问元素
at访问元素
front访问第一个元素
back访问最后一个元素

请注意:访问元素有以下几种访问方式

//auto遍历
for(auto : e : v2)
{
	cout << e << " ";
}
cout << endl;
//下标遍历
for (size_t i = 0; i < v1.size(); ++i)
{
	cout << v1[i] << " ";
}
cout << endl;
//正向迭代器遍历
auto it = v1.begin();
while (it != v1.end())
{
	cout << *(it) << " ";
	++it;
}
cout << endl;
//反向迭代器遍历
auto rit = v1.rbegin();
while(rit != v..rend())
{
	cout << *(rit) << " ";
	++rit;
}
cout << endl;

增删查改

函数名称功能
push_back尾插
pop_back尾删
find查找(是算法模块实现的,不是vector的成员函数)
insert在pos前插入val
erase删除pos位置的数据
swap交换两个vector的数据空间
operator[]像数组一样通过下标访问

迭代器

在这里插入图片描述
如当前图片所示:begin是在当前vector中的第一个元素的位置,end在当前vector最后一个元素的下一个位置,而反向迭代器正好相反。

迭代器失效问题

如果我们写这样一个代码

在这里插入图片描述

当程序执行到第14行时,直接奔溃了。这是什么原因呢?

实际上和当前这个迭代器有关,当前迭代器我们可以将其理解为是一个指针,当前指针本来指向的是vector的第一个元素的位置,而我们将其扩容后,实际上在底层经历了开辟新空间,拷贝元素,释放旧空间三个步骤,当这三个步骤结束后,原本指向第一个元素的指针已经失去了意义,成为了野指针,我们要访问这个野指针程序就会奔溃。因为我们使用的是一块已经被释放的空间。

如果总结下来:有以下几种情况可能会导致迭代器失效
1.会引起底层空间发生改变的操作:resize,reserve,insert,assign,push_back
2.指定位置删除元素

int main()
{
	vector<int> v{1,2,3,4,5,6};

	auto pos = find(v.begin(), v.end(), 5);
	v.erase(pos);
	cout << *(pos) << endl;
	return 0;
}

针对上述迭代器失效的解决办法,第一种情况,我们要在使用迭代器之前再次对迭代器进行赋值
第二种情况,我们要在使用erase时去接收返回值。


http://www.kler.cn/news/17618.html

相关文章:

  • macOS Monterey 12.6.5 (21G531) 正式版发布,ISO、IPSW、PKG 下载
  • Servlet原理
  • 由路由守卫引发的Angular DI inject思考
  • 【数据结构】二叉搜索树
  • TortoiseGit提示No supported authentication methods available异常
  • tab widget用法
  • 第一章(四):Django框架的模板(DTL):变量、标签、模板过滤器、模板继承、配置模板文件(staticfiles)
  • B树(B-tree、B-树)理论详解
  • SPSS如何进行方差分析之案例实训?
  • 蓝牙耳机哪款性价比高一些?2023年性价比最高的蓝牙耳机推荐
  • 一、spring Cloud Alibaba概述
  • No.046<软考>《(高项)备考大全》【专项2】《案例分析 - 计算题(中)》
  • API接口的应用
  • 高性能定时器--时间轮/多级时间轮
  • 用于无线传感器网络路由的改进leach协议(Matlab代码实现)
  • 06_Uboot顶层Makefile分析_前期所做内容
  • C++之异常处理
  • 国民技术N32G430开发笔记(15)- IAP升级 树莓派串口发送数据
  • 如何搭建chatGPT4.0模型-国内如何用chatGPT4.0
  • C语言将汉字保存到文件中
  • 如何显示文件夹的后缀和隐藏文件
  • 一分钟学会Flask框架的安装与快速使用
  • 诺派克ROPEX热封控制器维修RES-407/RES-406
  • 设计模式-创建型模式-(工厂、简单工厂、抽象工厂)
  • 有必要给孩子买台灯吗?分享四款高品质的护眼台灯
  • 处理 json 和 HttpMessageConverter--文件下载-ResponseEntity --SpringMVC 文件上传
  • 组态软件对比,未来10年发展趋势!
  • 【VAR | 时间序列】应用VAR模型时的15个注意点
  • [实训] 实验1-SPI数据传输基础实验(下)
  • 操作系统2(多处理器编程)