动态数组…

以下是Vector定义的源代码摘录(函数部分我就不写了)

用它来作为引子…

可以看到定义了很多类型,而真正的数据只有三个:

使用空间头尾和容量的尾…

 

Vector的迭代器:

Vector维护的是一个连续的线性空间,所以不论其元素型别是什么,普通指针都可以作为Vector的迭代器并满足所以的必要条件,因为Vector迭代器所需要进行的操作,普通指针天生就具备。

Vector支持随机存取,普通指针也有着这样的能力。

所以vector提供的是 Random Access Iterator.

可以看到上文的迭代器定义:

根据上述的定义,如果程序猿or媛们写出这样的代码:

实际上定义的是 int* ivite; 和 Shape* svite;…

 

Vector的数据结构:

Vector的数据结构非常简单:线性连续空间。

它以两个迭代器 start 和 finish 分别指向配置得来的连续空间中目前已被使用的范围,

用迭代器 end_of_storage 指向整块连续空间(包括备用空间)的尾端。

为了降低空间配置时的速度成本,vector实际配置的大小可能比需求量更大一些,以备将来可能扩充。

这便是容量(capacity)的概念。

运用start、finish、end_of_storage 三个迭代器,便可以轻易地提供首位标示,大小,容量,空容器判断,等等函数:

 

Vector的构造与内存管理:constructor、push_back

以代码为引导(认真看,相比侯捷的还多加了几个用例):

展示了一个vector从定义到增加减少元素等情况下的容量变化。

相信,如果认真看了这个代码的人,已经理解了Vector的内存增长规律了。

 

接下来是它的空间配置:

vector缺省使用alloc作为空间配置器,并据此另外定义了一个data_allocator,为的是更方便以元素大小为配置单位。

于是,data_allocator:allocate(n) 表示配置n个元素空间。

 

vector 提供了很多 constructs ,其中一个允许我们指定空间大小及初值:

uninitialized_fill_n()会根据第一参数的型别特征决定使用算法fill_n或者反复调用construct()来完成任务。

 

当我们以 push_back()将新元素插入于vector尾端时,该函数先检查是否有备用空间,如果有备用空间就直接构造元素,并调整finish,如果没有备用空间就扩充空间(重新配置空间,移动数据,释放原空间)。

insert_aux 是vector 的一个成员函数,其具体实现如下:

所以可以看到:

动态增加大小,是以原大小的两倍去配置另一块空间,然后将原数据拷贝过来。

所以,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。

 

vector 的元素操作:

pop_back, erase, clear, insert

vector提供的元素操作很多,这里选部分常用的讲。

pop_back 将尾端元素拿掉,并调整大小。

 

erase清除元素:

下图可以很清楚的表达:

erase(first,last)

如果 erase是清除某个位置上的元素:

上面这段代码比较清楚,就是把后面的元素往前覆盖了一位,然后清除最后一个元素。

 

insert插入元素:

insert有三种情况:

  1. 备用空间>=新增元素个数;插入点之后的现有元素>新增元素个数
  2. 备用空间>=新增元素个数;插入点之后的现有元素<=新增元素个数
  3. 备用空间<新增元素个数

以上三种情况的处理方法不相同,可以用三张图来说明:

1. 将前三个元素拷贝过去,然后插入新元素。

insert1

2. 先插入一部分元素,然后将前面的元素放到后面,再插入一部分元素。

insert2

3. 流程清晰,不讲解了。

insert3

它的源代码如下:

 

好像这里就结束了…Vector一些比较重要的操作。

【STL】Vector
Tagged on:
0 0 投票数
Article Rating
订阅评论
提醒

2 评论
最新
最旧 最多投票
内联反馈
查看所有评论

大神啊!!!!!