c++顺序容器内部实现

来源:互联网 发布:淘宝客优惠券 php源码 编辑:程序博客网 时间:2024/06/06 16:27

1、vector、list、deque的内部实现机制?

vector:vectorbuilt-in数组类似,是一个在堆上建立的一维数组,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[]操作符。vector因为存储在堆上,所以支持erase( ), resieze()(重新划分容器容量)等操作; vector不用担心越界当空间不够用的时候,系统会自动按照一定的比例(对capacity( )大小)进行扩充。在vector序列末尾添加(push_back( ))或者删除(pop_back( ))对象效率高,在中间进行插入或删除效率很低,主要是要进行元素的移动和内存的拷贝,原因就在于当内存不够用的时候要执行重新分配内存,拷贝对象到新存储区,销毁old对象,释放内存等操 作,如果对象很多的话,这种操作代价是相当高的。为了减少这种代价,使用vector最理想的情况就是事先知道所要装入的对象数目,用成员函式 reserve( )预定下来;vector最大的优点莫过于是检索(用operator[ ])速度在这三个容器中是最快的,

a、vector为了支持快速的随机访问,容器中的元素以连续的方式进行存放——每一个元素都紧挨着前一个元素进行存储;

b、当往容器内添加一个新的元素时,如果容器中没有空间容纳新的元素,此时,由于元素必须连续存储以便索引访问,所以不能在内存中随便找个地方存储这个心元素。于是,vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储卡就中的元素被复到新存储空间里,借着插入新元素,最后撤销旧的存储空间。为了实现vector容器的快速内存分配,在实际分配过程中的容量要比当前所需的空间多一些,vector容器预留出这些额外的存储区,用于存放心添加的元素。于是,不必为每一个新元素重新分配容器。(以最小的代价连续存储元素从而带来访问元素的遍历以弥补其存储空间代价)

c、由于vector进行连续存储,所以在vector里面需要定义一个容量capacity的概念,vector的size指的是当前容器中所具有的元素的个数,而capacity则指的是容器在需要重新分配内存空间前所能存储的元素总数,reserve则表示容器需要预留多少个元素的存储空间。capacity>=size,标准库中提供了reserve和capacity函数,程序员可以自己定义额外的存储空间或者容量。当vector的当前容量已经被消耗完全的时候,容器不得不分配新的存储空间,以加倍当前容量的分配策略是先重新分配。当然,vector的每种是先可自由选择内存分配策略,必要时才进行分配,分配多少内存取决于其具体的实现方式。

例程如下:

1、初始化部分

vector< int > ivec;

cout  << ivec.size() << << ivec,capacity() << endl;

for( vector< int >::size_type ix = 0;ix != 24;++ix) 

    ivec.push_back(i);

cout  << ivec.size() << << ivec,capacity() << endl;

输出结果: 0  0           24  32

2、预留额外空间

ivec.reserve(50);

cout << ivec.size() << ivec.capacity() << endl;

while(ivec.size() != ivec.capacity())

    ivec.push_back(0);

cout << ivec.size() << << ivec,capacity() << endl;

输出结果:24  50        50  50

3、重新分配空间

ivec.push_back(42);

cout << ivec.size() << << ivec,capacity() << endl;

输出结果:51  100


list: list的本质是一个双向链表(根据sgi stl源代码),内存空间不连续,通过指针进行操作。说道链表,它的高效率首先表现是插入,删除元素,进行排序等等需要移动大量元素的操作。显然链表没有检索操作operator[ ], 也就是说不能对链表进行随机访问,而只能从头至尾地遍历,这是它的一个缺陷。list有不同于前两者的某些成员方法,如合并list的方法splice( ), 排序sort( ),交换list 的方法swap( )等等。

a、不支持下标操作

b、当往容器内添加一个新的元素时,标准库只需要创建一个新的元素,然后将新元素连接在已存在的链表中,不需要重新分配存储空间,也不必复制任何已经存在的元素。


deque:deque 是一个double-ended queue是由多个连续内存块构成,deque是list和vector的兼容,分为多个块,每一个块大小是512字节,块通过map块管理,map块里保存每个块得首地址。因此该容器也有索引操作operator[ ],效率没vector高。另外,dequevector多了push_front( ) & pop_front( )操作。在两端进行此操作时与list的效率差不多。


2、顺序容器之间的比较?

a、vector和deque支持下标操作,list不支持下标操作

b、vector和deque容器均提供了对元素的快速随机访问,但是在容器的任意位置插入或者删除元素,避灾容器尾部插入和删除开销更大;而list类型在任何位置都能快速插入和删除,但是元素的随机访问开销较大

c、deque容器与vector容器在与deque的数据结构更为复杂,deque容器同时提供了高效的在其首部insert和erase操作,就如同在尾部进行操作一样

d、在deque容器首尾部插入元素不会使任何迭代器失效,而在首部uozhe尾部删除元素则只会使指向被删除元素的迭代器失效,在其他的任何位置删除或者插入都会使该容器的所有迭代器失效


原创粉丝点击