10.vector容器
之前我们已经学习了string容器,而本篇文章将进行vector容器的学习。
目录
一、vector容器介绍
二、vector容器的接口
1.默认成员函数
2.迭代器Iterator
3.容量Capacity
4.元素访问Element access
5.修改Modifiers
6.非成员函数重载
三、vector容器使用的细节
1.vector和string的区别
2.vector实现容器嵌套
3.initializer_list类
总结:
一、vector容器介绍
vector是STL的一个模板容器,实现的是顺序表结构,它与string容器有很多相似点,所以学习起来会相对轻松一点。这也体现出容器的优势了,在学会一种容器后,能快速学会其他容器的使用。而vector对比string的不同点是吸取了string设计的经验,删除了一些冗余接口,使用起来会更加舒适。
学习vector容器同样参考cplusplus.com这个网站
https://legacy.cplusplus.com/reference/vector/vector/?kw=vector
二、vector容器的接口
注:由于vector和string有很多相似点,所以不会再事无巨细地介绍,而是重点放在不同的地方
1.默认成员函数
重点来看构造函数
- 首先是一个全缺省构造,缺省参数是用于自定义内存池,基本不会用到,所以当成不传参即可
- 第二是用n个val值来进行初始化
- 第三个是用迭代器初始化
- 第四个是一个拷贝构造
析构函数就多介绍了,operator=通过拷贝构造实现
示例代码:
vector<int> v1;// 第一种
vector<int> v2(10, 1);// 第二种
vector<int> v3(v2.begin(), v2.end());// 第三种
其中<int>是一个模板参数,用于指定顺序表的数据类型
2.迭代器Iterator
迭代器也与string类似,可以看到这些接口都和string一样
由于begin()、end()以及这些后面的接口效果都和string类似,就不一一介绍了
示例代码:
可以看到迭代器的使用方式和string几乎一模一样,包括范围for也是一样
3.容量Capacity
容量的接口也是类似,并且还少了length接口
4.元素访问Element access
- 重载了[ ]操作符,用于访问数据,如果越界访问会抛异常
- at返回pos位置的数据的引用
- front返回头部数据引用,back返回尾部数据引用
- data用于返回用于存储数据的数组指针
5.修改Modifiers
整体和string还是类似的,emplace和emplace_back暂时不做讲解,因为涉及的知识比较复杂。
这块vector设计的比string要更简洁,如insert,只设计了三种重载,且只提供了迭代器的版本
示例代码:
那么vector没有find接口该如何查找呢,答案是使用C++标准库的统一定义的find模板函数。那么为什么string单独设计了find而vector又不需要呢?原因是字符串的查找比较复杂,设计字符、字符串的操作,而vector的查找比较简单,所以标准库中模板函数就够用了。
6.非成员函数重载
vector同样重载了关系比较运算符,比较逻辑和比较字符串类似,不过用的很少
注意:vector没有重载流插入和流提取运算符,所以不能直接用cin和cout进行输入输出,因为没有必要。我们可以使用迭代器或范围for来实现输入、输出操作,并且还能自定义输出格式。而string之所以需要重载是因为字符串会频繁输入和输出,并且字符串通常都是整个串直接输出即可,比如"hello"串就直接输出hello,不会在中间自定义格式。
三、vector容器使用的细节
1.vector和string的区别
两者底层都是通过数组存储,那能否通过vector来存储字符串呢?粗略想想是可以的,因为vector既然是模板容器,那也兼容字符类型,但在实际使用过程就能发现string不可被替代:
- 首先vector对标的是模板参数,实现的是顺序表结构,所以存储字符时末尾不会加上'\0',这就和C语言不兼容了,会导致很多问题
- 其次vector的接口和string又很多不同,用vector存储字符串时有很多字符串特定的操作都不能使用,如find查找一段字符串,流插入和流删除
2.vector实现容器嵌套
vector<容器类型>可以实现容器的嵌套存储。
如:vector<vector<int>>可以实现一个二维数组,vector<string>可以实现存储字符串的顺序表。
代码示例:
但这里的范围for涉及到了一个问题,已知范围for是循环把迭代器解引用的值拷贝到形参e中实现遍历,对于string这样的类型,此时就变成了深拷贝,多次的深拷贝就会浪费很多资源。所以此处建议加上引用以避免深拷贝:for ( const auto& : v2 )
3.initializer_list类
C++11对vector构造函数有了新的补充,我们重点介绍一个常用的。在此之前我们先了解一下initializer_list类,因为构造函数的形参用到了他。
1. 首先initializer_list是一个模板类,他有size、begin、end等成员函数。
2. initializer_list翻译过来是初始化列表,所以他的作用也和名字一样,用于初始化。他会将数据用{ }打包,再一键输送。如上面示例中演示的auto il = {10, 20, 30 },其中il的类型就是intializer_list<int>
3. 这和数组很类似,但区别是initializer_list被设计出来就是专门用于传递数据和初始化的,他在传递数据上更安全,并且还能调用成员函数获取相应信息
4. 使用时需要包括<initializer_list>头文件
有了initializer_list之后,我们可以更方便地初始化vector,可以使用任意数量个值去初始化
示例代码:
补充:typeid函数可以显示参数的真是类型
总结:
以上便是本篇文章的所有内容了,如果觉得有用的话可以点赞收藏加关注支持一下!