《21天学通C++(第7版)》——17.2 典型的vector操作

17.2 典型的vector操作

21天学通C++(第7版)
std::vector类的行为规范和公有成员是由C++标准定义的,因此,遵循该标准的所有C++编程平台都支持本章将介绍的vector操作。

17.2.1 实例化vector

vector是一个模板类,需要使用第14章介绍的方法进行实例化。要实例化vector,需要指定要在该动态数组中存储的对象类型:

要声明指向list中元素的迭代器,可以这样做:

如果需要可用于修改值或调用非const函数的迭代器,可使用iterator代替const_iterator。

鉴于std::vector有多个重载的构造函数,您可在实例化vector时指定它开始应包含的元素数以及这些元素的初始值,还可使用vector的一部分来实例化另一个vector。

程序清单17.1演示了几种实例化vector的方式。

程序清单17.1 各种实例化std::vector的方式:指定长度和初始值以及复制另一个vector中的值

分析:
上述代码演示了如何为整型具体化vector类,即实例化一个存储整型数据的vector。该vector名为vecIntegers,它使用了默认构造函数。在不知道容器最小需要多大,即不知道要存储多少个整数时,默认构造函数很有用。实例化vector的第2种和第3种方式如第10行和第13行所示,在这里,程序员知道vector至少应包含10个元素。注意,这并没有限制容器最终的大小,而只是设置了初始大小。第4种形式如第16行和第18行所示,它使用一个vector实例化另一个vector的内容,即复制vector对象或其一部分。这是所有STL容器都支持的构造函数。最后一种形式是使用迭代器。vecSomeElementCopied包含vecWithTenElements的前5个元素。

第4个构造函数只能用于类型类似的对象,因此可使用一个包含整型对象的vector来实例化vecArrayCopy——另一个整型vector,但如果其中一个vector包含的对象类型为float,代码将不能通过编译。

cbegin()和cend()是否导致编译错误?

如果您使用的编译器没有遵循C++11标准,请使用begin()和end()分别代替该程序中的cbegin()和cend()。

cbegin()和cend()的不同之处(优点)在于,它们返回一个迭代器,但较老的编译器不支持它们。
17.2.2 使用push_back()在末尾插入元素
实例化一个整型vector后,接下来需要在vector中插入元素(整数)。在vector中插入元素时,元素将插入到数组末尾,这是使用成员方法push_back完成的:

程序清单17.2演示了如何使用push_back()在std::vector中动态地添加元素。

程序清单17.2 使用push_back在vector中插入元素

输出:
.

分析:
第9~12行的push_back是vector类的一个公有成员方法,用于在动态数组末尾插入对象。请注意函数size ()的用法,它返回vector中存储的元素数。

C++11
初始化列表
C++11通过std::initialize_list<>支持初始化列表,让您能够像处理静态数组那样,在实例化vector的同时初始化其元素:

如果在程序清单17.2中使用这种语法,可节省3行代码,但这里没有这样做,因为编写本书时,Microsoft Visual C++ 2010编译器的std::vector实现不支持初始化列表。

17.2.3 使用insert()在指定位置插入元素

push_back在vector末尾插入元素。如果要在中间插入元素,该如何办呢?很多STL容器(包括std::vector)都包含insert()函数,且有多个重载版本。

其中一个版本让您能够指定插入位置:

另一个版本让您能够指定插入位置、要插入的元素数以及这些元素的值(都相同):

还可将另一个vector的内容插入到指定位置:

可使用迭代器(通常是由begin()或end()返回的)告诉insert()您想将新元素插入到什么位置。

也可将该迭代器设置为STL算法(如std::find()函数)的返回值。std::find()可用于查找元素,然后在这个位置插入另一个元素(这将导致查找的元素向后移)。
程序清单17.3演示了vector::insert()的各种重载版本。

程序清单17.3 使用函数vector::insert在指定位置插入元素

输出:

分析:
上述代码演示了insert函数的强大功能,它让您能够将值插入到容器中间。第17行的vector包含4个元素,每个元素都被初始化为90;然后,使用了成员函数vector::insert的各种重载版本。第23行在开头添加了一个元素;第26行在末尾添加了两个元素,它们的值都是45。第35行演示了如何将一个vector的元素插入到另一个vector中间(这里是第一个元素后面,偏移量为1)。

虽然函数vector::insert功能众多,但给vector添加元素时,应首选push_back()。

请注意,将元素插入vector时,insert()可能是效率最低的(插入位置不是末尾时),因为在开头或中间插入元素时,将导致vector类将后面的所有元素后移(为要插入的元素腾出空间)。根据容器中包含的对象类型,这种移动操作可能需要调用复制构造函数或赋值运算符,因此开销可能很大。在上述例子中,vector包含的是int对象,移动开销不是很大。但在其他情况下,情况可能并非如此。

如果需要频繁地在容器中间插入元素,应选择使用第18章将介绍的std::list。

您使用的C++编译器是否较老

在程序清单17.3中,函数DisplayVector()使用了C++11关键字auto来声明迭代器的类型,如第6行所示。对于这个示例以及后面的示例,如果要使用非C++11编译器编译它们,需要将auto替换为显式类型,这里为vector::const_iterator。

因此,如果您使用的是较老的编译器,需要将DisplayVector()修改成下面这样:

17.2.4 使用数组语法访问vector中的元素

可使用下列方法访问vector的元素:使用下标运算符([])以数组语法方式访问;使用成员函数at();使用迭代器。

程序清单17.1演示了如何创建一个包含10个元素的vector实例:

可使用类似于数组的语法访问并设置各个元素:

程序清单17.4演示了如何使用下标运算符([])访问元素。

程序清单17.4 使用数组语法访问vector中的元素

输出:

分析:
在第17、21和23行,像使用静态数组那样,使用下标运算符([])访问并设置了vector的元素。下标运算符接受一个从零开始的元素索引,与静态数组一样。注意到第15行的for循环将索引与vector::size()进行比较,确保它跨越vector的边界。

使用[]访问vector的元素时,面临的风险与访问数组元素相同,即不能超出容器的边界。使用下标运算符([ ])访问vector的元素时,如果指定的位置超出了边界,结果将是不确定的(什么情况都可能发生,很可能是访问违规)。

更安全的方法是使用成员函数at():

at()函数在运行阶段检查容器的大小,如果索引超出边界(无论如何都不能这样做),将引发异常。

下标运算符([ ])只有在保证边界完整性的情况下才是安全的,如前一个例子所示
17.2.5 使用指针语法访问vector中的元素
也可使用迭代器以类似于指针的语法访问vector中的元素,如程序清单17.5所示。

程序清单17.5 使用指针语法(迭代器)访问vector中的元素

输出:

分析:
在这个例子中,迭代器有点像指针,迭代器的用法很像指针算术运算,如第25和29行所示。在第25行,使用了解除引用运算符(*)来访问存储在vector中的值,而第29行使用了运算符++递增迭代器,使其指向下一个元素。第21行使用了std::distance来计算元素的偏移量(相对于开头的位置),这是根据begin()和指向元素的迭代器计算得到的。

17.2.6 删除vector中的元素

除支持使用push_back方法在末尾插入元素外,vector还支持使用pop_back函数将末尾的元素删除。使用pop_back将元素从vector中删除所需的时间是固定的,即不随vector存储的元素个数而异。程序清单17.6演示了如何使用函数pop_back删除vector末尾的元素。

程序清单17.6 使用pop_back删除最后一个元素

输出:

分析:
上述输出表明,第29行的pop_back函数将vector的最后一个元素删除,从而减少了vector包含的元素数。第32行再次调用size(),以证明vector包含的元素少了一个,如输出所示。

在程序清单17.3中,DisplayVector()只能接受整型vector作为参数,而在程序清单17.6中,它是个模板函数(第4-13行)。这有助于将该模板函数重用于浮点型vector:

该模板函数接受任何类型的vector作为参数,只要该类型支持运算符\,且其返回值可被cout理解。*
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

时间: 2024-08-21 11:19:57

《21天学通C++(第7版)》——17.2 典型的vector操作的相关文章

《21天学通C++(第7版)》导读

前言 21天学通C++(第7版) 对C++来说,2011是个很特别的年份.在这一年,C++11终于获批成为新标准,它新增了一些可提高编程效率的关键字和结构,让您能够编写更优质的代码.本书旨在帮助您循序渐进地学习C++11,其中的章节经过仔细编排,从实用的角度介绍这种面向对象的编程语言的基本知识.读者只需每天花1小时,在学完本书后,就能掌握C++11. 学习C++的最佳方式是动手实践.本书包含丰富的代码示例,有助于读者提高编程技能,请务必亲自动手尝试这些代码.这些代码片段都使用了(在本书编写时)最

《21天学通C语言(第6版•修订版)》一导读

前 言 21天学通C语言(第6版•修订版) 本书旨在引导读者在21天内学通C语言编程.虽然有来自诸如C++.Java和C#的激烈竞争,但很多初学编程者还是会选择C语言.正如第1天课程介绍的原因,选择C语言可确保您不会误入"歧途". 将本书作为自学C语言的教材是一个明智的决定.虽然市面上有很多有关C语言的图书,但本书介绍C语言的方式最为合理,也让读者学习起来最为容易.本书的前五版都登上了畅销书排行榜,这一事实表明我们的观点得到了读者的认同.本书是按读者每天阅读一章的方式编写的.读者不需要

《21天学通C语言(第6版•修订版)》一1.2 为何要使用C语言

1.2 为何要使用C语言 21天学通C语言(第6版•修订版) 在当前的计算机编程领域中,有大量的高级语言可供选择,如C.Perl.BASIC.Java和C#.这些都是非常卓越的语言,适合用于完成大部分编程任务.虽然如此,但基于以下几个原因,很多计算机专业人员认为C语言是其中最佳的: C语言功能强大.灵活.使用C语言能够完成的工作只受限于您的想象力,语言本身不会给您带来任何约束.C语言可用于完成操作系统.字处理器.图形.电子表格等项目,甚至可用于编写其他语言的编译器. C语言很流行,是专业程序员的

《21天学通C语言(第7版)》一导读

前言 21天学通C语言(第7版) 从书名便可看出,通过学习本书,你可以自学C程序设计语言.在众多语言(如C++.JAVA和C#)中,C仍然是学习程序设计语言的首选.第1课中将详细介绍其中的原因.选择C作为程序设计语言是明智之举. 与市面上其他C语言的书籍相比,本书的讲解逻辑更清晰,初学者更容易理解.之前的6个版本一直在畅销书排行榜上遥遥领先,广受读者赞誉!本书为读者量身定制,每天只需花一小时便可学完一课内容.读者不需要有任何编程经验,当然,如果有其他语言的基础(如BASIC),学起来会更快.本书

《21天学通C++(第7版)》——17.6 问与答

17.6 问与答 21天学通C++(第7版) **问:vector会改变其存储的元素的顺序吗? 答:**vector是一种顺序容器,元素的存储顺序与插入顺序相同. **问:要将元素插入到vector中,应使用哪个函数?元素将插入到vector的什么位置? 答:**成员函数push_back将元素插入到vector末尾. **问:哪个函数用于获悉存储在vector中的元素个数? 答:**成员函数size ()返回存储在vector中的元素个数.对于所有STL容器,该函数都如此. 问:随着vecto

《21天学通Java(第6版)》—— 1.5 组织类和类行为

1.5 组织类和类行为 21天学通Java(第6版) Java面向对象编程还涉及另外三个概念:继承.接口和包,这些都是用于组织类和类行为的机制. 1.5.1 继承 继承是面向对象编程中最重要的概念之一,直接影响您如何设计和编写Java类. 继承是一种机制,让一个类能够继承另一个类的所有行为和属性. 通过继承,一个类可自动拥有现有类的所有功能,因此只需定义与现有类不同的地方. 通过继承,所有的类(无论是您创建的类,还是Java类库中的类)都以严格的层次结构来组织. 继承其他类的类叫子类,被继承的类

《21天学通C语言(第7版)》一6.2 控制程序的执行

6.2 控制程序的执行 21天学通C语言(第7版) C程序默认的执行顺序是自上而下.从main()函数的起始位置开始,逐条执行语句,直至main()函数的末尾.然而,在实际的C程序中,很少严格按这样的顺序执行.C语言提供了各种程序控制语句,方便程序员控制程序的执行顺序.第4课介绍了一种程序控制语句--if语句,接下来介绍另外3种有用的控制语句: for语句: while语句: do...while语句. 6.2.1 for语句 for语句是由一条或多条语句组成的块.for语句有时也被称为for循

《21天学通Java(第6版)》—— 2.5 表达式和运算符

2.5 表达式和运算符 21天学通Java(第6版) 表达式是一条能够提供值的语句.最常见的是数学表达式,如下面的例子所示: 这3条语句都是表达式-它们提供了可被赋给变量的值.第1条语句将字面量3赋给变量x.第2条语句将变量x的值赋给变量y.在第3条语句中,乘法运算符*用来将x和y相乘,结果存储在变量z中. 表达式可以是任何变量.字面量和运算符的组合,也可以是方法调用,因为方法能够将一个值返回给调用它的类或对象. 您知道,表达式所提供的值称为返回值.在Java程序中,可将这个值赋给变量或以其他方

《21天学通Java(第6版)》—— 导读

前言 21天学通Java(第6版) 有些革命出其不意地吸引了全世界的眼球.Twitter.Linux操作系统和电视剧<Cupcake Wars>的异军突起颠覆了传统思维模式. 而Java语言的巨大成功却在人们的意料之中.自从Java语言于17年前面世以来,人们就对它充满殷切的期望.当Java融入到Web浏览器时,公众以无比的热情欢迎这种新语言的到来. Sun公司创始人Bill Joy在介绍这种新语言时,毫不掩饰其孤注一掷的心态:"15年来,我们一直力图开发出一种更佳的编程语言和环境,