深入剖析deque容器实现

deque简介

       deque是双向开口的连续性存储空间。虽说是连续性存储空间,但这种连续性只是表面上的,实际上它的内存是动态分配的,它在堆上分配了一块一块的动态储存区,每一块动态存储区本身是连续的,deque自身的机制把这一块一块的存储区虚拟地连在一起。

       它首次插入一个元素,默认会动态分配512字节空间,当这512字节空间用完后,它会再动态分配自己另外的512字节空间,然后虚拟地连在一起。deque的这种设计使得它具有比vector复杂得多的架构、算法和迭代器设计。它的性能损失比之vector,是几个数量级的差别。所以说,deque要慎用。

deque数据结构

        逻辑数据结构示意图:

                 

                                                              图1 逻辑结构示意图

        实际数据结构示意图:

                

                                                                 图2 实际结构示意图

 数据结构实现

template<class _Ty, class _Ax>
class deque
{
private:
	_Mapptr _Map;		// pointer to array of pointers to blocks
	size_type _Mapsize;	// size of map array
	size_type _Myoff;	// offset of initial element
	size_type _Mysize;	// current length of sequence
};
 一、deque的中控器      
        我们发现这里有一个_Map成员变量。大家注意,这可不是STL中的map。这个_Map是一个指针,指向一块特殊的内存地址,这里保存着指向deque动态申请的所有512字节内存空间的首地址。deque先用一段小的连续空间顺序存放了一个一个指针,然后这些顺序存放的指针再各自指向用来真正存放数据的512字节连续性空间。当_Map指向的这块空间不够存放内存指针的时候,就会另觅一块更大的连续性空间,然后把指针一个一个复制过去,并销毁旧的空间。利用这种数据结构,deque就能方便地模拟自身的存储区是连续性空间的假象,并且可以实现双向插入删除的功能我们看一下deque的数据结构图,如图3所示。
               
                                                                      图 3 内部实现结构    
          _Map所指的一小块连续空间就是deque的中央控制器,其中每个元素(此处称为一个节点,node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是deque的储存空间主体。STL 允许我们指定缓冲区大小,默认值0表示将使用512 bytes 缓冲区。
          当中控器使用率已经满载时,便需要再找一块更大的空间来做map,配置策略间reallocate_map(),新的map可以容纳更多的节点,也就是更多的缓冲区,如图4是扩展新空间的示意图,新增缓冲区是在原来基础上进行,没有复制操作,这种扩展方式避开了“重新配置、复制、释放”的轮回,代价是复杂的迭代器架
       
                                                   图 4 扩展新空间实现方式 
     从deque扩展新空间的方式,可以看出deque没有capacity(),不需要reserce(size_type n)。这是因为deque由动态分配的连续空间组合而成,随时可以增加一段新的空间链接起来。它没有必要像vector那样“因旧空间不足而重新分配2倍的空间,然后复制元素,再释放旧空间。
 二、deque的迭代器
           在STL中,我们都可以通过解引用的方式得到迭代器所指的值,为了能够从“deque内部结构”中得到中某个元素的确切位置,那么deque的迭代器应该具备怎么结构,我们可以考虑以下几点。首先,需要知道该元素位于哪个缓冲区的哪个位置;其次,一旦迭代器前进和后退有可能会跳跃至上一个或下一个缓冲区,为了判断跳跃的条件就需要知道,当前元素所在缓冲区的首尾指针。最后,如果 前进或后退必须跳跃至下一个或上一个缓冲区。为了能够正确跳跃,deque必须随时掌握管控中心(map),通过map可以知道跳跃的缓冲区。 所以在迭代器中需要定义如下参数,deque的迭代器如图5所示:
  • 当前元素的指针
  • 当前元素所在缓冲区的起始指针,
  • 当前元素所在缓冲区的尾指针,
  • 指向map中指向所在缓区地址的指针。
  
                                                    图 5 迭代器示意图

deque对用户屏蔽了复杂的内存管理操作, 我们平时操时都是按照"逻辑结构"方式进行,也就是可动态插入、删除的一维数组,大大简化了用户使用,如图6所示。其实deque最大的任务就是管理这些分段的连续空间上,维护其整体连续的假象,并提供随机存取的接口。

图 6 deque<string>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值