C++之旅-vector

前言

标准库类型vector表示对象集合,并且所有的对象类型相同。由于它常常“容纳”其他对象,因此常称作容器。vector也是一个类模板。编译器根据模板创建类型或函数的过程称为实例化,当使用模板时,需要指出编译器应把类或函数实例化成何种类型。

初始化

与string类型一样,vector也有很多种方式进行初始化:

1
2
3
4
5
6
7
vector<int> v1;    //v1是一个空的vector,它包含的元素是int类型
vector<int> v2(v1); //v2包含了v1中的副本
vector<int> v2 = v1; //等价于v2(v1)
vector<string> v3(3,"hello"); //包含3个重复string元素,每个元素的值为“hello”
vector<string> v4(8); //包含8个string类型的vector,执行8次初始化
vector<char> v5{'a','b','c'}; //包含了三个char类型的元素,并都有相应的初始值
vector<T> v5={'a','b','c'}; //等价于v5{'a','b','c'}

通常情况,我们可以只提供元素数量,而不需要提供初始值,库会根据类型自动进行一个值初始化,例如:

1
vector<int> v6(6);   //6个元素,并且每个元素都初始化为0

以下是一些常见错误的初始化:

1
2
3
vector<int> a = "hello"; //错误,vector a只能存储int类型
vector<int> b = 8; //错误,如果需要使得元素值为8,则需要使用直接初始化的方式并且指定元素个数
vector<string> c("hello"); //错误,字符串字面值不能用于构建vector的对象

特别注意,以下几种情况是有区别的:

1
2
3
4
vector<int> v1(8)    //包含8个元素,每个元素被初始化为0
vector<int> v2{8} //包含一个函数,元素值为8
vector<int> v3(8,1) //包含8个元素,值都为1
vector<int> v3{8,1} //包含两个元素,值分别为8和1

vector基本操作

vector有以下基本操作

1
2
3
4
5
6
vector<int> v;
v.push_back(10); //将10添加到v
v.push_back(8); //将8添加到v的尾部
v.empty(); //如果v不包含任何元素,返回真
v.size() //返回元素个数
v[1] //返回第2个元素的引用

注意:定义一个空vector,再在运行向其中添加元素,会比创建时指定容量大小,再添加,会更加高效
解释:通常vector将元素连续存储,当添加的元素超出了原先分配的大小时,就需要重新申请空间,并把原来的元素移到新的位置。vector实现通常会比空间需求分配更大的空间,以避免在添加元素时频繁地重新分配空间并进行移动。既然如此,在一开始就设定大小,并且对其进行初始化就显得没有必要,初始化反而会影响效率,除非vector将要保存的元素都是一样的。

特别注意,不能使用下标形式添加元素,例如:

1
v[2] = 10;

因为添加之前,不存在下标为2的元素。下标运算符只能用于访问已经存在的元素

迭代器

所有的标准容器都可以使用迭代器。这些容器类型都拥有名为begin和end的成员,分别返回指向第一个元素和尾元素的下一个位置。
例如,可以像下面的方式使用begin和end:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include<string>
#include<vector>
using namespace std;
int main ()
{
/*将字符串中的字母都转换为大写*/
string s ("hello world");
for (auto it = s.begin (); it != s.end (); ++it)
{
*it = toupper (*it);
}
cout << s << endl;
}

声明迭代器类型it指向s.begin(),遍历每一个元素,将其转换为大写。其中++it让迭代器类型指向下一个元素,直到it指向s.end()。这里使用!=作为循环判断条件是因为很多迭代器并没有<运算符,因此并非所有的标准库类型都可以使用它。但是==和!=是所有标准库容器都定义了的。

对于迭代器之间,可以使用算数运算,例如it=it+2迭代器it的位置向前移动了两个元素,而两个迭代器相减,得到它们之间的元素间隔数。

总结

  • vector是模板而不是类型,不存在包含引用的vector,因为引用不是对象。
  • 下标运算符只能用于访问已经存在的元素。
  • 不能使用下标形式添加元素。
  • 定义一个空vector,再在运行向其中添加元素,会比创建时指定容量大小,再添加,会更加高效。
守望 wechat
关注公众号[编程珠玑]获取更多原创技术文章
出入相友,守望相助!