STL 源码剖析:deque 的实现原理

虽然 deque 从表面上来说,它采用连续的空间,并且支持随机访问,即其迭代器为 random_access_iterators 类型。而且相比 vector,它还支持 push_front()。

//
//

​ 但是实际上,deque 只是逻辑上的连续空间。它需要维护一个特殊的东西,叫做 deque 的中控器。该中控器主要由一个二级指针和一个 size 构成,(即可以理解为,该中控器是一个一级指针数组,下面我们用这个词来讲解)。

//
//

​ 中控器是一个指针数组,数组中的每一个指针指向一个缓冲区 (即一块连续空间)。

​ 初始时,会首先配置出这个中控器的空间,然后配置出需要的若干个缓冲区的空间,将这若干个缓冲区放在中控器的中间部分(使得头尾两端可扩充的缓冲区数量一样大)。

注意:只有配置了的才有空间,而且配置仅仅代表分配空间,该空间时原始的,并没有初始化。即,中控器初始时,里面的每个值都还没有构造,缓冲区也是同理。我们会在需要的时候进行构造。

//
//

​ 当然,这就还会涉及到中控器空间不足的问题。(后述)

//
//

​ deque 的迭代器中包含 4 个重要部分,该迭代器指向的缓冲区 (即该迭代器指向中控器的哪一个位置),该缓冲区的首指针,尾指针 以及 当前的指针位置 cur。即,对于首迭代器来说,我们每一次构造都是先 – cur,然后在 cur 这个位置上进行构造;对于尾迭代器,我们在 cur 位置上进行构造,然后 ++ cur。(这里不包括缓冲区用尽的情况)

你可以将迭代器理解为一个指针,指向中控器的某一个位置,但这个指针同时还包含一些额外的信息。

//
//

​ 那么中控器是如何维护的呢。其实就是两个迭代器,首和尾迭代器。可以把首尾迭代器想象成两个指针,指向中控器中目前使用的首位置和尾位置。所以当缓冲区用尽时,假设是首迭代器的缓冲区用尽,我们就会配置一个新的缓冲区,然后将缓冲区的首指针放在中控器中的首迭代器的前一个位置,然后更新首迭代器;如尾迭代器的缓冲区用尽,我们就会配置一个新的缓冲区,然后将缓冲区的首指针放在中控器中的尾迭代器的后一个位置,然后更新尾迭代器。(当然,这里未考虑中控器空间不足的情况)。

//
//

​ 而逻辑上,deque 的迭代器是 random_access_iterators,所以我们还需要为它重载 ++,+=, --, -=, -, +, <, >,[] 等运算符。即满足 random_access_iterators 的所有操作。

//
//

​ 当中控器空间不足时,会考虑到能否通过在中控器中移动 [start, finish+ 1) 使得 start 和 finish 两端有多余空间(足以满足需求的新增数量),而决定是否真正的配置新的中控器空间。

​ 若配置新的空间,就需要将原来的内容拷贝到新空间中,然后释放旧空间。

//
//
实现还是有些复杂,但原理是这样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值