标准库vector类型
摘要
vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。
我们把vector成为容器,是因为它可以包含其他对象。一个容器中的所有对象都闭学式同一种类型的。
vector是一个类模板(class template),使用它可以定义保存string对象的vector,或保存int值的vector,又或是保存自定义的类类型对象(如Sales_item)的vector。
1 声明
vector声明时必须说明vector保存的对象类型,通过将类型放在类模板名称后面的尖括号中来指定类型。
//定义vector对象 类型为vector<int>,该类型含有若干个int类型 变量名为ivec
vector<int> ivec; //ivec holds objects of type int
//定义的变量名为Sales_vec 保存的元素时Sales_item类型的对象
vector<Sales_item> Sales_vec; //holds Sales_items
2 vector对象的定义和初始化
几种初始化vector对象的方式
代码 | 含义 |
---|---|
vector v1; | vector保存类型为T的对象。默认构造函数v1为空 |
vector v2(v1); | v2是v1的一个副本 |
vector v3(n,i); | v3 包含n个值为i的元素 |
vecot v4(n); | v4含有值初始化的元素的n个副本 |
2.1 创建确定元素的个数
要创建非空的vector对象,必须给出初始化元素的值。
vector<int> ivec1; //ivec1 holds objects of type int
//ivec1和ivec2 的vector对象类型都是int类型,把ivec1 vector对象复制到另一个ivec2 vector对象时,ivec2 vector对象中每一个元素都初始化为原vector中相应的元素的副本。
vector<int> ivec2(ivec1); //ok: copy elements of ivec1 into ivec2
vector<string> svec(ivec1); //error:svec holds strings, not ints
也可用元素个数和元素值对vector对象进行初始化。构造函数用元素个数来决定vector对象保存元素的个数,用元素值来指定每个元素的初始值。
vector<int> ivec4(10, -1); //10 elements, each initialized to -1
vector<string> svec(10, "hi!"); //10 strings, each initialized to "hi!"
要注意的是:虽然可以对给定元素个数的vector对象预先分配内存,但更高效的方法是先初始化一个空vector对象,然后再动态地增加元素。
关键概念:vector对象动态增长
vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效地添加元素。
2.2 值初始化
如果没有给定指定元素的初始化式,标准库将自行提供一个元素初始值进行值初始化
如果vector保存内置类型(如int类型)的元素,那么标准库将用0值创建元素初始化式。
vector<int> fvec(10); //10 elements, each initialized to 0
如果vector保存的是含有构造函数的类类型(如string)的元素,标准库将用该类型的默认构造函数创建元素初始化式:
vector<string> svec(10); //10 elements, each an empty string
特殊情况1: 一些有自定义构造函数但没用默认构造函数的类,在初始化这种类型的vector对象时,程序员就不能仅提供元素个数,还需要提供元素初始值
特殊情况2: 元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。
3 vector对象的操作
vector操作
代码 | 含义 |
---|---|
v.empty() | 如果v为空,则返回true,否则返回false() |
v.size() | 返回v中元素的个数 |
v.pushback(t) | 在v的末尾增加一个值为t的元素 |
v[n] | 返回v中位置为n的元素 |
v1 = v2 | 把v1中元素替换为v2中元素的副本 |
v1 == v2 | 如果v1和v2相等,则返回true |
!=, <, <=, >, >= | 保持这些操作符惯有的含义 |
3.1 vector对象的size1
//成员函数**size**返回相应的vector类定义的**size_type**的值
//使用size_type类型时,必须指出该类型是在哪里定义的。vector类型总是包括vector的元素类型
vector<int>::size_type //ok
vector::size_type //error
3.2 向vector添加元素
push_back()操作接受一个元素值,并将其添加到vector对象的后面
//read words from the standard input and store them as elements in a vector
string word;
vector<string> text; //empty vector
while (cin >>word){
text.push_back(word); //append word to text
}
3.3 vector下标操作
可以通过vector中对象的位置来访问vector对象中的元素。通常采用下标操作符([]操作符)来获取元素。类似string类型的下标操作.
vector的下标操作符接受一个值,并返回vector中该对应位置的元素。vector元素的位置从0开始。
//使用for循环把vector中的每个元素值都重置为0:
//reset the elements in the vector to zero
for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;
//和string类型的下标操作符一样,vector下标操作的结果为左值。另外,
//和string对象的下标操作类似,这里用size_type类型作为vector下标的类型
Insert:C++有些函数可以声明为内联函数(inline),编译器遇到内联函数就会直接扩展为相应代码,而不是进行实际的函数调用。
3.4 下标操作不添加元素
vector下标操作不能添加元素。
vector<int> ivec; //empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; //disaster; ivec has no elements
上述代码视图在ivec中插入10个元素,值依次为0~9的整数。但是ivec是空的vector对象,而下标操作只能用于获取已存在的元素。
正确的做法:
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec.push_back(ix); //ok:adds new element with value ix
通过下标操作进行赋值时,不会添加任何元素。必须是已存在的元素 才能用下标操作符进行索引。
下标操作符仅能提取确实已存在的元素
vector<int> ivec; //empty vector
cout << ivec[0]; //Error:ivec has no elements!
vector<int ivec2(10); //vector with 10 elements
cout << ivec[10]; //Error:ivec has elements 0~9;
警告:试图对不存在的元素进行下标操作时程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致PC机和其他应用中最常见的安全问题。