3.3.3 其他vector操作(1)
除了push_back之外,vector还提供了几种其他操作,大多数都和string的相关操作类似,表3.5列出了其中比较重要的一些。
表3.5:vector支持的操作
|
表3.5:vector支持的操作
|
|
v.empty()
|
如果v不含有任何元素,返回真;否则返回假
|
|
v.size()
|
返回v中元素的个数
|
|
v.push_back(t)
|
向v的尾端添加一个值为t的元素
|
|
v[n]
|
返回v中第n个位置上元素的引用
|
|
v1 = v2
|
用v2中元素的拷贝替换v1中的元素
|
|
v1 = {a,b,c... }
|
用列表中元素的拷贝替换v1中的元素
|
|
v1 == v2
|
v1和v2相等当且仅当它们的元素数量
相同且对应位置的元素值都相同
|
|
v1 != v2
|
v1和v2相等当且仅当它们的元素数量
相同且对应位置的元素值都相同
|
|
<, <=, >, >=
|
顾名思义,以字典顺序进行比较
|
访问vector对象中元素的方法和访问string对象中字符的方法差不多,也是通过元素在vector对象中的位置。例如,可以使用范围for语句处理vector对象中的所有元素:
- vector<int> v{1,2,3,4,5,6,7,8,9};
- for (auto &i : v) // 对于v中的每个元素(注意:i是一个引用)
- i *= i; // 求元素值的平方
- for (auto i : v) // 对于v中的每个元素
- cout << i << " "; // 输出该元素
- cout << endl;
第一个循环把控制变量i定义成引用类型,这样就能通过i给v的元素赋值,其中i的类型由auto关键字指定。这里用到了一种新的复合赋值运算符(参见1.4.1节,第12页)。如我们所知,+=把左侧运算对象和右侧运算对象相加,结果存入左侧运算对象;类似的,*=把左侧运算对象和右侧运算对象相乘,结果存入左侧运算对象。最后,第二个循环输出所有元素。
vector的empty和size两个成员与string的同名成员(参见3.2.2节,第87页)功能完全一致:empty检查vector对象是否包含元素然后返回一个布尔值;size则返回vector对象中元素的个数,返回值的类型是由vector定义的size_type类型。
要使用size_type,需首先指定它是由哪种类型定义的。vector对象的类型总是包含着元素的类型(参见3.3节,第97页):
- vector<int>::size_type // 正确
- vector::size_type // 错误
各个相等性运算符和关系运算符也与string的相应运算符(参见3.2.2节,第88页)功能一致。两个vector对象相等当且仅当它们所含的元素个数相同,而且对应位置的元素值也相同。关系运算符依照字典顺序进行比较:如果两个vector对象的容量不同,但是在相同位置上的元素值都一样,则元素较少的vector对象小于元素较多的vector对象;若元素的值有区别,则vector对象的大小关系由第一对相异的元素值的大小关系决定。
只有当元素的值可比较时,vector对象才能被比较。一些类,如string等,确实定义了自己的相等性运算符和关系运算符;另外一些,如Sales_item类支持的运算已经全都罗列在1.5.1节(第20页)中了,显然并不支持相等性判断和关系运算等操作。因此,不能比较两个vector<Sales_item>对象。
计算vector内对象的索引
使用下标运算符(参见3.2.3节,第93页)能获取到指定的元素。和string一样,vector对象的下标也是从0开始计起,下标的类型是相应的size_type类型。只要vector对象不是一个常量,就能向下标运算符返回的元素赋值。此外,如3.2.3节(第95页)所述的那样,也能通过计算得到vector内对象的索引,然后直接获取索引位置上的元素。
举个例子,假设有一组成绩的集合,其中成绩的取值是从0到100。以10分为一个分数段,要求统计各个分数段各有多少个成绩。显然,从0到100总共有101种可能的成绩取值,这些成绩分布在11个分数段上:每10个分数构成一个分数段,这样的分数段有10个,额外还有一个分数段表示满分100分。这样第一个分数段将统计成绩在0到9之间的数量;第二个分数段将统计成绩在10到19之间的数量,以此类推。最后一个分数段统计满分100分的数量。
按照上面的描述,如果输入的成绩如下:
- 42 65 95 100 39 67 95 76 88 76 83 92 76 93
则输出的结果应该是:
- 0 0 0 1 1 0 2 3 2 4 1