vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。和string对象一样,标准库负责管理存储元素的相关内存。我们把vector称为容器,是因为它可以包含其他对象。一个容器中的所有对象都必须是同一种类型的。
使用vector之前,必须包含相应的头文件。本书给出的例子,都是假设已作了相应的using声明:
#include <vector>
using std::vector;
vector是一个类模板(classtemplate)。模板允许程序员编写单个类或函数定义,这个类和函数定义可用于不同的数据类型上。因此,我们可以定义保存string对象的vector,或保存int值的vector,又或是保存自定义的类类型对象(如Sales_item对象)的vector。将在第16章介绍如何定义程序员自己的类模板。幸运的是,使用类模板时只需要简单了解类模板是如何定义的就可以了。
声明从类模板产生的某种类型的对象,需要提供附加信息,信息的种类取决于模板。以vector为例,必须说明vector保存何种对象的类型,通过将类型放在类模板名称后面的尖括号中来指定类型:
vector<int> ivec; //ivecholds objects of typeint
vector<Sales_item> Sales_vec; //holdsSales_items
和其他变量定义一样,定义vector对象要指定类型和一个变量的列表。上面的第一个定义,类型是vector<int>,该类型即是含有若干int类型对象的vector,变量名为ivec。第二个定义的变量名是Sales_vec,它所保存的元素是Sales_item类型的对象。
vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此,vector<int>和vector <string>都是数据类型。
3.3.1vector对象的定义和初始化
vector类定义了好几种构造函数(2.3.3节),用来定义和初始化vector对象。表3-4列出了这些构造函数:
表3-4几种初始化vector对象的方式
vector<T>v1;
|
vector保存类型为T的对象。默认构造函数v1为空。
|
vector<T>v2(v1);
|
v2是v1的一个副本。
|
vector<T>v3(n,i);
|
v3包含n个值为i的元素。
|
vector<T>v4(n);
|
v4含有值初始化的元素的n个副本。
|
1.创建确定个数的元素
若要创建非空的vector对象,必须给出初始化元素的值。当把一个vector对象复制到另一个vector对象时,新复制的vector中每一个元素都初始化为原vector中相应元素的副本。但这两个vector对象必须保存同一种元素类型:
vector<int> ivec1; //ivec1holds objects of typeint
vector<int> ivec2(ivec1); //ok: copy elements ofivec1intoivec2
vector<string> svec(ivec1); //error:svecholdsstrings,notints
可以用元素个数和元素值对vector对象进行初始化。构造函数用元素个数来决定vector对象保存元素的个数,元素值指定每个元素的初始值:
vector<int> ivec4(10, -1); //10elements, each initialized to-1
vector<string> svec(10, "hi!"); //10strings, each initialized to "hi!"
关键概念:vector对象动态增长
vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效地添加元素。因为vector增长的效率高,在元素值已知的情况下,最好是动态地添加元素。
正如第4章将介绍的,这种增长方式不同于C语言中的内置数据类型,也不同于大多数其他编程语言的数据类型。特别地,如果读者习惯了C或Java的风格,由于vector元素连续存储,可能希望最好是预先分配合适的空间。但事实上,为了达到连续性,C++的做法恰好相反,具体原因将在第9章探讨。
虽然可以对给定元素个数的vector对象预先分配内存,但更有效的方法是先初始化一个空vector对象,然后再动态地增加元素(我们随后将学习如何进行这样的操作)。
2.值初始化
如果没有给出元素的初始化式,那么标准库将提供一个值初始化的(valueinitialized)元素初始化式。这个由库生成的初始值用于初始化容器中的每个元素。而元素初始化式的值取决于存储在vector中元素的数据类型。
如果vector保存内置类型(如int类型)的元素,那么标准库将用0值创建元素初始化值:
vector<string> fvec(10); //10elements, each initialized to0
如果向量保存类类型(如string)的元素,标准库将用该类型的默认构造函数创建元素初始值:
vector<string> svec(10); //10elements, each an empty string
第12章将介绍一些有自定义构造函数但没有默认构造函数的类,在初始化这种类型的Vector对象时,程序员就不能仅提供元素个数,还需要提供元素初始值。
还有第三种可能性:元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。
习题3.11下面哪些vector定义不正确?
(a)vector<vector<int> >ivec;
(b)vector<string>svec=ivec;
(c)vector<string>svec(10,”null”);
习题3.12下列每个vector对象中元素个数是多少?各元素的值是什么?
(a) vector<int> ivec1;
(b) vector<int> ivec2(10);
(c) vector<int> ivec3(10,42);
(d) vector<string> svec1;
(e) vector<string> svec2(10);
(f) vector<string> svec3(10,”hello”);
3.3.2vector的操作
vector标准库提供许多类似于string对象的操作,表3-5列出了几种最重要的vector操作。
表3-5vector操作
v.empty()
|
如果v为空,则返回true,否则返回false。
|
v.size()
|
返回v中元素的个数。
|
v.push_back(t)
|
在v的末尾增加一个值为t的元素。
|
v[n]
|
返回v中位置为n的元素。
|
v1=v2
|
把v1的元素替换为v2中元素的副本。
|
v1==v2
|
如果v1与v2相等,则返回true。
|
!=, <, <=, >, >=
|
保持这些操作符惯有的含义。
|
1.vector对象的size
empty和size操作类似于string类型的相关操作(3.2.3节)。成员函数size返回相应vector类定义的size_type的值。
使用size_type类型时,必须指出该类型是在哪里定义的。vector类型总是包括vector的元素类型:
vector<int>::size_type //ok
vector::size_type //error
2.向vector添加元素
push_back()操作接受一个元素值,并将它作为一个新的元素添加到vector对象的后面,也就是“插入(push)”到vector对象的“后面(back)”:
// read words from the standard input and store them as elements in a vector
string word;
vector<string> text; //emptyvector
while (cin >> word) {
text.push_back(word); //appendwordtotext
}
该循环从标准输入读取一系列string对象,逐一追加到vector对象的后面。首先定义一个空的vector对象text。每循环一次就添加一个新元素到vector对象,并将从输入读取的word值赋予该元素。当循环结束时,text就包含了所有读入的元素。
3.vector的下标操作
vector中的对象是没有命名的,可以按vector中对象的位置来访问它们。通常使用下标操作符来获取元素。vector的下标操作类似于string类型的下标操作(3.2.3节)。
vector的下标操作符接受一个值,并返回vector中该对应位置的元素。vector元素的位置从0开始。下例使用for循环把vector中的每个元素值都重置为0:
//reset the elements in thevectorto zero
for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;
和string类型的下标操作符一样,vector下标操作的结果为左值,因此可以像循环体中所做的那样实现写入。另外,和string对象的下标操作类似,这里用size_type类型作为vector下标的类型。
在上例中,即使ivec为空,for循环也会正确执行。ivec为空则调用size返回0,并且for中的测试比较ix和0。第一次循环时,由于ix本身就是0,则条件测试失败,for循环体一次也不执行。
关键概念:安全的泛型编程
习惯于C或Java编程的C++程序员可能会觉得难以理解,for循环的判断条件用!=而不是用<来测试vector下标值是否越界。C程序员难以理解的还有,上例中没有在for循环之前就调用size成员函数并保存其返回的值,而是在for语句头中调用size成员函数。
C++程序员习惯于优先选用!=而不是<来编写循环判断条件。在上例中,选用或不用某种操作符并没有特别的取舍理由。学习完本书第二部分的泛型编程后,你将会明白这个习惯的合理性。
调用size成员函数而不保存它返回的值,在这个例子中同样不是必需的,但这反映了一个良好的编程习惯。在C++中,有些数据结构(如vector)可以动态增长。上例中循环仅需要读取元素,而不需要增加新的元素。但是,循环可以容易地增加新元素,如果确实增加了新元素的话,那么测试已保存的size值作为循环的结束条件就会有问题,因为没有将新加入的元素计算在内。所以我们倾向于在每次循环中测试size的当前值,而不是在进入循环时,存储size值的副本。
我们将在第7章学习到,C++中有些函数可以声明为内联(inline)函数。编译器遇到内联函数时就会直接扩展相应代码,而不是进行实际的函数调用。像size这样的小库函数几乎都定义为内联函数,所以每次循环过程中调用它的运行时代价是比较小的。
4.下标操作不添加元素
初学C++的程序员可能会认为vector的下标操作可以添加元素,其实不然:
vector<int> ivec; //emptyvector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; //disaster:ivechas 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 valueix
必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。
警告:仅能对确知已存在的元素进行下标操作
对于下标操作符([]操作符)的使用有一点非常重要,就是仅能提取确实已存在的元素,例如:
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
试图获取不存在的元素必然产生运行时错误。和大多数同类错误一样,不能确保执行过程可以捕捉到这类错误,运行程序的结果是不确定的。由于取不存在的元素的结果是未定义的,因而不同的实现会导致不同的结果,但程序运行时几乎肯定会以某种有趣的方式失败。
本警告适用于任何使用下标操作的时候,如string类型的下标操作,以及将要简要介绍的内置数组的下标操作。
不幸的是,试图对不存在的元素进行下标操作是程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致PC机和其他应用中最常见的安全问题。
分享到:
相关推荐
vector操作vector操作vector操作
Vector出品的hexview工具可以用来查看文件的十六进制码,转换数据格式,浏览 Hex文件,可以设置显示方式:字节、字、双字。每行显示字节数等。可实现s19 hex bin文件之间的相互转换,填充,计算CRC,地址偏移等功能...
纯c语言的向量vector实现,实现c++中vector的一些基本的特性和操作,适用于一些只支持c语言的平台上使用vector数据结构,包含测试用例以及函数的使用范例
Pixel2vector2是一款专为ps用户打造的增强插件,主要方便用户将位图转换为矢量图形,这样就可以进行图像的编辑等操作了,在安装之前需要先安装相应的PS插件,然后就可以正常使用了,小编还为大家整理了Pixel2vector...
自己实现的vector,优化的动态内存管理
Vector产品手册电子版
VectorCAST License安装手册.pdf
Vector CANoe 使用介绍
The series in Vector Optimization contains publications in various fields of optimization with vector-valued objective functions, such as multiobjective optimization, multi criteria decision making, ...
vector nti 破解文件for 11.5
CAN FD是博世和Vector共同开发的新一代总线,文档是Vector对于CAN FD的详细介绍
赠送jar包:arrow-vector-0.8.0.jar; 赠送原API文档:arrow-vector-0.8.0-javadoc.jar; 赠送源代码:arrow-vector-0.8.0-sources.jar; 赠送Maven依赖信息文件:arrow-vector-0.8.0.pom; 包含翻译后的API文档:...
C语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC语言头文件 VECTORC...
vector的详细用法.txt vector的详细用法.txt vector的详细用法.txt
赠送jar包:arrow-vector-0.10.0.jar; 赠送原API文档:arrow-vector-0.10.0-javadoc.jar; 赠送源代码:arrow-vector-0.10.0-sources.jar; 赠送Maven依赖信息文件:arrow-vector-0.10.0.pom; 包含翻译后的API文档...
Alex Smola et al.A tutorial on support vector regression.Statistics and Computing,2004 In this tutorial we give an overview of the basic ideas underlying Support Vector (SV) machines for function ...
Startup with Vector SLP4 User Manual---Vector Davinci官方帮助配置手册
该资源在VS2008 SP1 IDE中实现,主要功能是介绍VC++中vector的使用方法,包括vector的定义、写入数据、读取数据、清空数据以及如何将vector中的数据元素进行随机打乱顺序等。将对你掌握vector的使用起到巨大的帮助。...
计算vector中所有元素之和/* 编写程序,处理一个vector<string> ,其元素都表示整型值/浮点型,计算vector中所有元素之和 */
Vector Magic 是一款功能强大的应用程序,能够轻松将位图图片转换成矢量图输出。Vector Magic 是一款功能强大的桌面应用程序,它能够通过易用且人性化的操作引导用户将自己电脑上的位图图片(又名点阵图、光栅)自动...