注意,在使用前要包含vector对应的头文件:

#include

vector是同一种类型的对 象的集合,每个对象都有一个对应的整数索引值。和string对象一样,标准库负责管理存储元素的相关内存。我们把vector称为容器,是因为它可以包 含其他对象。一个容器中的所有对象都必须是同一种类型的。我们将在第9章更详细地介绍容器。

使用vector之前,必须包含相应的头文件。本书给出的例子,都是假设已作了相应的using声明:

#include

using std::vector;

vector 是一个类模板(class template)。模板允许程序员编写单个类或函数定义,这个类和函数定义可用于不同的数据类型上。因此,我们可以定义保存string对象的 vector,或保存int值的vector,又或是保存自定义的类类型对象(如Sales_item对象)的vector。将在第16章介绍如何定义程 序员自己的类模板。幸运的是,使用类模板时只需要简单了解类模板是如何定义的就可以了。

声明从类模板产生的某种类型的对象,需要提供附加信息,信息的种类取决于模板。以vector为例,必须说明vector保存何种对象的类型,通过将类型放在类模板名称后面的尖括号中来指定类型:

vector ivec;                 // ivec holds objects of type int

vector Sales_vec;  // holds Sales_items

和其 他变量定义一样,定义vector对象要指定类型和一个变量的列表。上面的第一个定义,类型是vector,该类型即是含有若干 int类型对象的vector,变量名为ivec。第二个定义的变量名是Sales_vec,它所保存的元素是Sales_item类型的对象。

vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此,vector和vector 都是数据类型。

3.3.1  vector对象的定义和初始化

vector类定义了好几种构造函数(2.3.3节),用来定义和初始化vector对象。表3-4列出了这些构造函数:

表3-4  几种初始化vector对象的方式

vector  v1;

vector保存类型为T的对象。默认构造函数v1为空。

vector v2(v1);

v2是v1的一个副本。

vector v3(n, i);

v3包含n个值为i的元素。

vector v4(n);

v4含有值初始化的元素的n个副本。

1. 创建确定个数的元素

若要创建非空的vector对象,必须给出初始化元素的值。当把一个vector对象复制到另一个vector对象时,新复制的vector中每一个元素都初始化为原vector中相应元素的副本。但这两个vector对象必须保存同一种元素类型:

vector ivec1;                // ivec1 holds objects of type int

vector ivec2(ivec1);       // ok: copy elements of ivec1 into ivec2

vector svec(ivec1);    // error: svec holds strings, not ints

可以用元素个数和元素值对vector对象进行初始化。构造函数用元素个数来决定vector对象保存元素的个数,元素值指定每个元素的初始值:

vector ivec4(10, -1);     // 10 elements, each initialized to -1

vector svec(10, "hi!"); // 10 strings, each initialized to "hi!"

关键概念:vector对象动态增长

vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效地添加元素。因为vector增长的效率高,在元素值已知的情况下,最好是动态地添加元素。

正如 第4章将介绍的,这种增长方式不同于C语言中的内置数据类型,也不同于大多数其他编程语言的数据类型。特别地,如果读者习惯了C或Java的风格,由于 vector元素连续存储,可能希望最好是预先分配合适的空间。但事实上,为了达到连续性,C++的做法恰好相反,具体原因将在第9章探讨。

虽然可以对给定元素个数的vector对象预先分配内存,但更有效的方法是先初始化一个空vector对象,然后再动态地增加元素(我们随后将学习如何进行这样的操作)。

2. 值初始化

如果没有给出元素的初始化式,那么标准库将提供一个值初始化的(value initialized)元素初始化式。这个由库生成的初始值用于初始化容器中的每个元素。而元素初始化式的值取决于存储在vector中元素的数据类型。

如果vector保存内置类型(如int类型)的元素,那么标准库将用0值创建元素初始化值:

vector fvec(10); // 10 elements, each initialized to 0

如果向量保存类类型(如string)的元素,标准库将用该类型的默认构造函数创建元素初始值:

vector svec(10); // 10 elements, each an empty string

第12章将介绍一些有自定义构造函数但没有默认构造函数的类,在初始化这种类型的Vector对象时,程序员就不能仅提供元素个数,还需要提供元素初始值。

还有第三种可能性:元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。

习题

习题3.11  下面哪些vector定义不正确?

(a) vector< vector > ivec;

(b) vector svec = ivec ;

(c) vector svec(10,”null”);

习题3.12  下列每个vector对象中元素个数是多少?各元素的值是什么?

(a) vector ivec1;

(b) vector ivec2(10);

(c) vector ivec3(10,42);

(d) vector svec1;

(e) vector svec2(10);

(f) vector svec3(10,”hello”);

3.3.2  vector的操作

vector标准库提供许多类似于string对象的操作,表3-5列出了几种最重要的vector操作。

表3-5  vector操作

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::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 text;        // empty vector

while (cin >> word) {

text.push_back(word);  // append word to text

}

该循环从标准输入读取一系列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 the vector to zero

for (vector::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 ivec;   // empty vector

for (vector::size_type ix = 0; ix != 10; ++ix)

ivec[ix] = ix; // disaster: ivec has no elements

上述程序试图在ivec中插入10个新元素,元素值依次为0到9的整数。但是,这里ivec是空的vector对象,而且下标只能用于获取已存在的元素。

这个循环的正确写法应该是:

for (vector::size_type ix = 0; ix != 10; ++ix)

ivec.push_back(ix);  // ok: adds new element with value ix

 
   

必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。

警告:仅能对确知已存在的元素进行下标操作

对于下标操作符([]操作符)的使用有一点非常重要,就是仅能提取确实已存在的元素,例如:

vector ivec;      // empty vector

cout << ivec[0];        // Error: ivec has no elements!

vector ivec2(10); // vector with 10 elements

cout << ivec[10];      // Error: ivec has elements 0...9

试图获取不存在的元素必然产生运行时错误。和大多数同类错误一样,不能确保执行过程可以捕捉到这类错误,运行程序的结果是不确定的。由于取不存在的元素的结果是未定义的,因而不同的实现会导致不同的结果,但程序运行时几乎肯定会以某种有趣的方式失败。

本警告适用于任何使用下标操作的时候,如string类型的下标操作,以及将要简要介绍的内置数组的下标操作。

C++ Vector 使用总结相关推荐

  1. OpenCV 笔记(08)— 二维点、三维点、基于 Mat 的 std::vector 等常用数据结构的定义和输出

    1. 定义和输出二维点 Point2f p2(3, 4);cout << "[二维点] is "<< endl << p2 << e ...

  2. c++中的vector的常见使用

    #include <iostream> #include <vector> #include <string> using namespace std; int m ...

  3. 向量算子优化Vector Operation Optimization

    向量算子优化Vector Operation Optimization 查看MATLAB命令View MATLAB Command 示例显示Simulink®编码器™ ,将生成向量的块输出,设置为标量 ...

  4. java vector search_java.util.Vector.retainAll()方法实例

    全屏 retainAll(Collection> c)方法用于仅保留此向量包含在指定Collection的元素.换言之,删除这个向量的所有元素未包含在指定Collection. 声明 以下是ja ...

  5. C++ 向量(vector) 的使用

    向量(vector)是什么 向量(vector)是属于STL(Standard Template Library, 标准模板库)中的一种随机访问数组的类型. 使用的时候需要使用#include < ...

  6. C++ 笔记(23)— STL vector 类(实例化 vector、末尾插入、指定位置插入、数组方式访问元素、指针方式访问元素、删除元素、大小与容量区别)

    1. vector 特点 vector 是一个模板类,提供了动态数组的通用功能,具有如下特点: 在数组末尾添加元素所需的时间是固定的,即在末尾插入元素的所需时间不随数组大小而异,在末尾删除元素也如此: ...

  7. 比较ArrayList、LinkedList、Vector

    翻译人员: 铁锚 翻译时间: 2013年12月2日 原文链接: ArrayList vs. LinkedList vs. Vector 1. List概述 List,就如图名字所示一样,是元素的有序列 ...

  8. C++ stl vector介绍

    转自: STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if ...

  9. 【stanford C++】容器III——Vector类

    主要介绍如下5个容器类--Vector, Stack,Queue,Map和Set,各个都表示一重要的抽象数据类型.另外,各个类都是一些简单类型的值的集合,所以称它们为容器类. 暂且我们先不需要知道它们 ...

  10. STL vector list deque区别与实现

    1 vector 向量 相当于一个数组     在内存中分配一块连续的内存空间进行存储.支持不指定vector大小的存储.STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacitu ...

最新文章

  1. Gym 100883J palprime(二分判断点在凸包里)
  2. Hadoop学习笔记(8) ——实战 做个倒排索引
  3. 开源社区ITGeek介绍
  4. 如何在linux系统下对文件夹名有空格的文件
  5. linux生成表格文件大小,如何为linux中的文件夹生成清单(文件列表及其大小和数量)...
  6. linux之多任务的同步与互斥
  7. python根据数据生成图像_从三个numpy数组生成图像数据
  8. go java gc_图解Golang的GC垃圾回收算法
  9. 单目相机提高标定精度的经验(转载)
  10. centos系统时间不准
  11. 出错也很美的404页面设计模板
  12. 独家 | 腾讯无人车首次曝光,还把车子开上了四环
  13. [hgo学习]-tutorial 03
  14. android编程入门
  15. STL inserter
  16. 收款码三合一生成系统源码
  17. c语言里的pow函数(好理解,易懂)
  18. 鸿洋,郭霖Android开发大牛:从入门到精通系列学习路线以及进阶Android高级工程师书籍介绍
  19. 怎么将iphone上的照片导出到本地文件
  20. 【STM32笔记】低功耗模式配置及避坑汇总

热门文章

  1. USB学习6---Linux Android USB软件架构设计
  2. LCD 显示异常定位分析方法
  3. Eclipse如何生成jar包
  4. WinCE启动次数的记录
  5. ubuntu下的win交叉编译
  6. 【转】Ubuntu VI基本用法
  7. Hibernate修改命名策略
  8. 继续C#开发or转做产品
  9. puppet最新源码包安装学习笔记
  10. ASP调用存储过程详解。