C++抽象编程——STL(4)——vector类

本来一直想着把这个放在第一个写的,但是为了配合我们的数据结构老师的课程,以加深自己对数据结构的认识,所以把栈和队列放在前面,现在终于有机会写这这个重头戏了。
vector,我相信很多人都听过这个东西,那么为什么它那么有名呢?肯定是有道理的。《programming abstraction in C++》这本书把它称为最有价值的类,

The Vector class

这些类中最有价值的集合类之一是Vector类,它提供了一个设施类似于我们以前在编程方面几乎肯定遇到的数列。 数组从编程初期开始就已经有了。和大多数语言一样,C++支持数组,关于数组我们有机会再总结。C++中的数组有,一些弱点,其中包括:

  • 数组被分配一个固定的大小,不能随后更改。(Arrays are allocated with a fixed size that you can’t subsequently change)
  • 即使数组具有固定的大小,C ++也不允许程序员可以随意改变大小。 因此,使用数组的程序通常需要一个额外的变量来跟踪元素的数量。(Even though arrays have a fixed size, C++ does not make that size available to the programmer. As a result, programs that work with arrays typically need an additional variable to keep track of the number of elements.)
  • 传统数组不支持插入和删除元素。(Traditional arrays offer no support for inserting and deleting elements)
  • C++数组不会判断书否越界。 例如,如果您创建一个包含25个元素的数组,然后尝试在下标位置50处选择一个值值,C++将简单地查看第50个元素的内存地址,并返回它的值。(C++ makes no effort to ensure that the elements you select are actually present in the array. For example, if you create an array with 25 elements and then try to select the value at index position 50, C++ will simply look at the memory addresses at which element 50 would appear if it existed.)

vector类通过以抽象数据类型的形式重新实现数组概念来解决这些问题。 您可以在任何应用程序中使用vector类代替数组,通常在源代码中几乎没有任何变化,最多只能降低效率。 实际上,一旦你有了vector类,就不太可能会使用数组,(也就是说你可以把vector看做是数组的升级版本)除非你真的必须实现像Vector这样的类(这并不奇怪),我们常常在它的底层结构中使用数组。 然而,作为Vector类的用户,我们暂时没必要对该基础结构深究,我们可以将数组技能留给实现抽象数据类型的程序员。
作为一个vector的用户,我们一定要对一些事件的不同性引起关注,并需要找出下列问题的答案:
1. * 如何指定Vector中包含的对象的类型?*(How is it possible to specify the type of object contained in a Vector?)
2. 如何创建一个Vector类的实例对象?(How does one create an object that is an instance of the Vector class?)
3. Vector类中存在什么方法来实现其抽象行为?(What methods exist in the Vector class to implement its abstract behavior?)

下面的三个部分就针对这三个问题来按顺序探索它们的答案。

Specifying the base type of a Vector

在C++中,集合类通过指定它们包含的对象的类型,在类名后面的尖括号中键入名称。例如,vector< int >类代表其元素为整数的vector,vector < char >指定其元素为字符的vector,vector< string >指定元素为字符串的vector。 括号内的类型称为集合的基本类型。就是下面的格式:

vector< base type >;

像这种包括了基本类型规范的类在面向对象中称为参数化类(Classes that include a base-type specification are called parameterized classes in the object-oriented community)。 在C++中,参数化类通常被称为模板(templates),这反映了C ++编译器将vector< int >,vector< char >和vector< string >作为独立的类共享一个共同的结构的事实。 vector作为一个模板,其中唯一的区别是向量包含什么类型的值。现在,你需要了解的是如何使用模板; 至于实现基本模板的过程,以后再说。

Declaring a Vector object

抽象数据类型背后的原理之一是,用户应该能够将它们视为内置原始类型。因此,正如你将通过编写一个声明来声明整数变量一样,就像这样:
int n;
所以我们也应该可以这样来声明一个vector:
vector< int > vec;
很好,确实是,在C++中就像你所做的一样,这样子就声明了一个名为vec的新的变量。他的数据类型就是你尖括号里面阐述的那样为int型,所以结合起来,这表示的就是我们声明了一个名为vec的int型的vector。

Vector operations

当我们声明一个vector变量时,它便是一个空向量(empty vector),这意味着它不包含任何元素。但是空的vector并没有什么用,所以我们需要学习的第一件事是如何向vector对象添加新元素。通常的方法是调用add方法,它在Vector的末尾添加一个新元素。 例如,如果vec是前面部分中声明的整数的空vector,则执行下面的代码:

vec.push_back(10);
vec.push_back(20);
vec.push_back(40);

这样我们就把三个元素——10,20,40——装进了vector中。它们就像字符串中的字符一样,都是从0开始计数的,所以你建立的vector就像下面的图一样:
这里写图片描述

与以后中将要介绍的更原始的数组类型不同,向量的大小不是固定的,这意味着您可以随时添加其他元素。例如,在程序中,你可以调用:

vec.push_back(50);

这样子,我们就在原先的vec的尾部添加了一个值(50)。此时的vector变为:
这里写图片描述
测试一下吧(代码和测试图我放一张图上):
这里写图片描述

现在,先让我们来看看vector在STL中有哪些的常用的方法吧,不多说,老方法,打开VS,跳到它的声明定义里去看一眼:
这里写图片描述

详细内容自维基百科(https://zh.wikipedia.org/wiki/Vector_(STL)

vector 类别是以容器(Container) 模式为基准设计的,也就是说,基本上它有 begin(),end(),size(),max_size(),empty() 以及 swap() 这几个方法。所以vector又称为容器。

访问元素的方法

方法用途
vec[i]访问下标值为i的元素引用。 (下标值从零起算,故第一个元素是vec[0])
vec.at(i)访问下标值为i的元素的引用,用at()访问会做数组边界检查,如果访问越界将会抛出一,这是与运算符[]的唯一差异。我们在字符串中提到过的。
vec.front()返回vector第一个元素的引用。
vec.back()返回vector最后一个元素的引用。

新增或移除元素的方法

方法用途
vec.push_back(n)在vector后面添加一个元素n
vec.pop_back()移除vector后的一个元素
vec.insert(Iterator,value)插入一个或多个元素至 vector 内的任意位置。值得注意的是insert()方法要求插入的位置,是元素的迭代器位置,而不是元素下标位置。
vec.erase(Iterator,value)删除 vector 中一个或多个元素。要求插入的位置,是元素的迭代器位置,而不是元素下标位置。
vec.clear()清空所有元素。

获取长度/容量

方法用途
vec.size()获取 vector 目前持有的元素个数。
vec.empty()如果 vector 内部为空,则传回 true 值
vec.capacity()获取 vector 目前可容纳的最大元素个数。这个方法与存储器的配置有关,它通常只会增加,不会因为元素被删减而随之减少。(就是相当于容器的容量

重新配置/重置长度

方法用途
vec.reserve()如有必要,可改变 vector 的容量大小(配置更多的存储器)。容量只能增加,不可以减少
vec.resize()改变 vector 目前持有的元素个数。

迭代 (Iterator)

方法用途
vec.begin()返回一个Iterator,它指向 vector 第一个元素。
vec.end()返回一个Iterator,它指向 vector 最尾端元素的下一个位置(请注意:它不是最末元素)。
vec.rbegin()回传一个反向Iterator,它指向 vector 最尾端元素的。
vec.rend()回传一个Iterator,它指向 vector 的第一个元素。

确实这个容器的方法有点多,但是看过我前几篇的文章的话,估计很快就会理解pop,push,还有clear等常见的功能。这里提到了迭代器,至于是什么,我们学过数据结构的都知道,我们栈类跟队列类内部都有个指针,一个指向的是首元素,另外一个指向的是最后一个元素的上端。所以迭代器又称为游标(cursor)。是我们在容器(container,例如链表或阵列)上遍访的接口。下一篇我们就重点以代码的形式来介绍一下这些方法的用途。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值