现在的位置: 首页 > 综合 > 正文

【C++ STL】序列式容器Vector

2013年10月20日 ⁄ 综合 ⁄ 共 2990字 ⁄ 字号 评论关闭

【C++ STL】序列式容器Vector

1. vector概述

      vector的数据安排以及操作方式,与array非常相似。两者的唯一差别在于array是静态分配,一旦配置就不能改变。而vector是动态空间分配,随着元素的加入,它的内部机制会自动扩展空间来容纳新元素。Vector实现的技术,关键在于其对大小的控制以及当空间重新配置时数据的移动效率。一旦vector旧空间满载,如果客户端在每新增一个元素,vector内部只是重新分配一个元素空间,实不明智,因此,在vector内部的设计机制中加入了未雨绸缪的考虑。

2.vector的函数列表

为了可以使用vector,必须在你的头文件中包含下面的代码:

      #include <vector>

      Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性时间复杂度。

函数列表如下:

Constructors 构造函数

Operators 对vector进行赋值或比较

assign() 对Vector中的元素赋值

at() 返回指定位置的元素

back() 返回最末一个元素

begin() 返回第一个元素的迭代器

capacity() 返回vector所能容纳的元素数量(在不重新分配内存的情况下)

clear() 清空所有元素

empty() 判断Vector是否为空(返回true时为空)

end() 返回最末元素的迭代器(译注:实指向最末元素的下一个位置)

erase() 删除指定元素

front() 返回第一个元素

get_allocator() 返回vector的内存分配器

insert() 插入元素到Vector中

max_size() 返回Vector所能容纳元素的最大数量(上限)

pop_back() 移除最后一个元素

push_back() 在Vector最后添加一个元素

rbegin() 返回Vector尾部的逆迭代器

rend() 返回Vector起始的逆迭代器

reserve() 设置Vector最小的元素容纳数量

resize() 改变Vector元素数量的大小

size() 返回Vector元素数量的大小

swap() 交换两个Vector

3.vector的迭代器

  vector维护的是一个连续线性空间,所以vector不论其元素型别为何、普通指针都可以作为vector的迭代器,因为vector迭代器所需要的操作行为,如operator *,operator ->, operator --,opeartor++,operator -=,普通指针天生都具备,所以vector提供的是random
Access Iterators。

源码如下:

template<class T>
class Vector{
typedef T value_type;
       typedef T* iterator;
       ......
};


如果客户端写出如下定义:

vector<double>::iterator dVec;
vector<Shape>::iterator sVec;


则dvec的型别为double*,sVec的型别为Shape*;

4.vector的数据结构

vetcor所采用的数据结构非常简单:连续线性空间,它以两个迭代器类型start和finish来分别表示vetcor分配的空间的开始位置和结束位置,迭代器end_of_storage表示配置的空间未使用的空间的尾端即备用空间,

template<class T,class Alloc=alloc>
class Vector{
........
iterator start;
iterator finish;
iterator end_of_storage;
.........
};


因此运用start,finish,end_of_storage可以很方便的获得首尾标识,vector的大小(finish-start),vector的容量(end_of_storage-start),空容器判断,最前端元素值,最后端元素值,

template<class T,class Alloc=alloc>
class vector{
. ......
    iterator begin(){
return start;
}
iterator end(){
return end;
}
size_type size()const{
return size_type(end-start);
}
bool empty()const{
return begin()==end();
}
.........
};


5.vector的内存管理

vector的迭代器就是最简单的指向容器内类型的指针。其内部有三个指针,start(指向数据存储区的首地址),finish(已使用的数据区的尾端),end_of_storage(指向容量尾端,容量一般富余),当遇到满载的情况,finish指针和
end_of_storage 指针相等,也就是容量用完的时候,如果继续插入元素,就会扩容。

需要扩容的时候,空间适配器就会从新寻找一块更大的内存空间(因为vector内部是一块连续的内存),然后start指向新内存首地址,原始数据复制,新数据插入,同时更新finish以及end_of_storage即可。扩容的规模一般是原始容量的两倍。vector空间是按照动态增加大小的,所谓动态增加并不是在原空间之后在接新空间(因为无法保证原空间后面还有可配置的空间),而是以原大小的两倍另外配置一块更大的区块,然后将原内容拷贝过去,并释放原空间。因此,对vector的操作,一旦引起空间的重新配置,指向原空间的所有迭代器将全部失效,这点要引起注意。当我们以push_back()将新元素插入vector的尾端时,该函数首先将检查是否有还有备用空间,如果有就直接在备用空间上构造元素,并调整finish的大小,如果没有备用空间就扩充空间(重新配置,移动数据,释放原空间)。

测试程序:

#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
vector<int> ivec(2,9);
cout<<"size="<<ivec.size()<<endl;      //size=2
cout<<"capacity="<<ivec.capacity()<<endl;   //capacity=2;
ivec.push_back(1);
cout<<"size="<<ivec.size()<<endl;      //size=3
cout<<"capacity="<<ivec.capacity()<<endl;   //capacity=4;
ivec.push_back(2);
cout<<"size="<<ivec.size()<<endl;      //size=4
cout<<"capacity="<<ivec.capacity()<<endl;   //capacity=4;
ivec.push_back(3);
cout<<"size="<<ivec.size()<<endl;      //size=5
cout<<"capacity="<<ivec.capacity()<<endl;   //capacity=8;
return 0;
}


【上篇】
【下篇】

抱歉!评论已关闭.