数组尽管很灵活,但使用起来还是很多不方便。为此,C++ 语言定义了扩展的“抽象数据类型”(Abstract Data Type,ADT),放在“标准库”中。
对数组功能进行扩展的一个标准库类型,就是“容器” vector。顾名思义,vector “容纳”着一堆数据对象,其实就是一组类型相同的数据对象的集合。
头文件和命名空间
vector 是标准库的一部分。要想使用 vector,必须在程序中包含 <vector>
头文件,并使用std
命名空间。
# include<vector>
using namespace std;
在 vector 头文件中,对 vector 这种类型做了定义;使用 #includ
引入它之后,并指定命名空间 std
之后,我们就可以在代码中直接使用 vector 了。
vector 的基本使用
vector 其实是 C++ 中的一个“类模板”,是用来创建类的“模子”。所以在使用时还必须提供具体的类型信息,也就是说,这个容器中到底要容纳什么类型的数据对象;具体的形式是在 vector 后面跟一个尖括号 <>,里面填入具体类型信息。
vector<int> v;
(1)初始化
跟数组相比,vector 的初始化更加灵活方便,可以应对各种不同的需求。
// 默认初始化,不含任何元素
vector<int> v1;
// 列表初始化(拷贝初始化)
vector<char> v2 = {'a', 'b', 'c'};
// 等价,省略等号的列表初始化
vector<char> v3{'a', 'b', 'c'};
// 只定义长度,元素初值默认初始化,容器中有 5 个 0
vector<short> v4(5);
// 定义长度和初始值
vector<long> v5(5, 100); // 5 个 long 类型的元素且有相同值为 100
这里有几种不同的初始化方式:
- 默认初始化一个 vector 对象,就是一个空容器,里面不含任何元素
- C++ 11 之后可以用花括号括起来的列表,对 vector 做初始化;等号可以省略;这种方式是把一个列表拷贝给了 vector,也称为“拷贝初始化”
- 可以用小括号表示初始化 vector 的长度,并且可以给所有元素指定相同的初始值;这种方式叫做“直接初始化”
(2)访问元素
vector 是包含了数据对象的“容器”,在这个容器集合中,每个数据对象都会有一个编号,用来做方便快速的访问;这个编号就是“索引”( index)。同样可以用下标操作符来获取对应索引的元素,这一点跟数组非常相似。
cout << "v5[2] = " << v5[2] << endl;
v5[4] = 66;
// v5[5] = 123; // 严重错误!不能越界访问索引
需要注意:
- vector 内元素的索引,也是从 0 开始
- vector 索引最大值为(vector 长度 -1),不能越界访问;如果直接越界访问并赋值,有可能导致非常严重的后果,出现安全问题
(3)遍历所有元素
vector 中有一个可以调用的函数 size(),只要调用它就能直接得到 vector 的长度(即元素个数):
cout << v5.size() << endl;
调用的方式是一个 vector 对象后面跟上一个点,再跟上 size()。这种基于对象来调用的函数叫做“成员函数”。这样我们就可以非常方便地用 for 循环遍历元素:
for(int i = 0; i < v5.size(); i++)
out << v5[i] << "\t";
当然,用范围 for 循环同样非常简单:
for (int num: v5)
cout << num << "\t";
(4)添加元素
vector 的长度并不是固定的,所以可以向一个定义好的 vector 添加元素。
// 在定义好的vector中添加元素
v5.push_back(69);
for (int num: v5)
cout << num << "\t";
这里的 push_back
同样是一个成员函数,调用它的时候在小括号里传入想要添加的数值,就可以让 vector 对象中增加一个元素了。
这就使得我们在创建 vector 对象时不需要知道元素个数,使用更加灵活,避免了数组中的缺陷。
下面的代码创建了一个空 vector,并使用添加元素的方式给它赋值为倒序的10~1:
vector<int> vec;
for (int i = 10; i > 0; i--)
{
vec.push_back(i * 2 + 1)
}
for (int num: vec)
cout << num << "\t";
vector 和数组的区别
- 数组是更加底层的数据类型;长度固定,功能较少,安全性没有保证;但性能更好,运行更高效
- vector是模板类,是数组的上层抽象;长度不定,功能强大;缺点是运行效率较低
除了 vector 之外,C++ 11 还新增了一个 array 模板类,它跟数组更加类似,长度是固定的,但更加方便、更加安全。所以在实际应用中,一般推荐对于固定长度的数组使用 array,不固定长度的数组使用 vector。