STL 源码剖析之 deque

定义

是一种双向开口的连续线性空间,可以在头尾两端分别做元素的插入和删除

  • 允许O(1)时间内对头端进行元素的插入或移除操作

没有容量的概念,因为它是以动态的分段连续空间合成,随时可以增加一段新的空间并连接起来

  • 一旦有必要在deque的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个deque的头端或尾端

  • 因此非必要不使用deque,如果要对deque进行排序,就要先把deque复制到vector上,将vector排序,再复制会deque

deque的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的借口,

避开了“重新配置、复制、释放”的轮回,代价则是复杂的迭代器架构




deque实现

迭代器

在64位机器、g++10.3下,deque::iterator的大小为32

deque的迭代器总共有四个指针:

  • cur(指向当前元素在buffer中的位置)

  • first(指向当前buffer的头部)

  • last(指向当前buffer的尾部)

  • node(指向当前的缓冲区对应的迭代器在中控器上的位置)


组成

在64位机器、g++10.3下,deque的大小为80

deque采用一块所谓的map(不是map容器)作为主控

这里所谓map是一小块连续空间,其中每个元素(称为节点node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区

缓冲区才是deque的储存空间主体,SGI STL 允许我们指定缓冲区大小,默认值0表示将使用512bytes缓冲区

deque主要由四个部分组成:

  • start(头iterator,指向deque的第一个元素)32字节

  • finish(尾iterator,指向deque最后一个元素的下一个节点)32字节

  • pointer(map_pointer;map是一块连续的内存空间,上面存放的是指向buffer的指针;所以map_pointer是指向该数组的一个指针;也就是T**类型)8字节

  • map_size(size_type,map中继器的大小,表示map内有多少个指针)8字节


源码




基本用法

deque的构造

//    构造函数的四种方式
deque<string> words1{"the", "is", "deque"};
deque<string> words2(words1.begin(), words1.end());
deque<string> words3(words1);
deque<string> words4(5, "YES");

deque的迭代器

//    iterator正向迭代器,+1是向右边走
for (deque<string>::iterator it = w.begin(); it != w.end(); ++ it) {}
//reverse_iterator反向迭代器,+1向左走
for (deque<string>::reverse_iterator it = w.rbegin(); it != w.rend(); ++ it) {}

deque的常用函数

word4.front();    //    获取第一个元素

word4.back();    //    返回最后一个元素

word4.size();    //    返回容器的大小

word4.push_back("NO");    //    把元素放入末尾

word4.pop_back();    //    移除最后一个元素

word4.push_front("SS");    //    把元素放到头部

word4.pop_front();    //    移除第一个元素

word4.empty();    //    判断是否为空

//    erast 移除元素
words4.erase(words4.begin());    //    移除某个位置的元素
words1.erase(words1.begin() + 2, words1.end());    //    移除某个区间的元素

//max_size

//shrink_to_fit

//at

//assign

//emplace_back

//emplace_front

//swap



API的使用

insert

//    作用:将元素插入到指定的位置上
words.insert(words.begin() + 1, words4.begin(), words4.end());    //    第一个参数是位置,后面是要插入的容器的内容
words.insert(words.begin() + 3, "strat");    //    指定位置插入元素
words.insert(words.begin() + 3, 5, "IS");    //    位置,重复次数,重复的数据

由于deque是可以两端进行扩充的,插入元素又会引入元素移动问题,进而带来拷贝构造的开销

所以在插入时首先进行判断插入位置距离首位哪边比较短,移动距离较短的一边,最大化的减少开销




to do list


 上一篇
STL 源码剖析之 map STL 源码剖析之 map
STL中的红黑树特点RB-tree不仅是一个二叉搜索树,而且必须满足以下规则: 1、每个节点不是红色就是黑色 2、根节点是黑色 3、如果节点为红,其子节点必须为黑 4、任一节点到NULL(树尾端)的任何路径,所含的黑色节点数必须相同
2022-10-22
下一篇 
STL 源码剖析之 vector STL 源码剖析之 vector
实现 vector 中有三个指针:指向使用空间的头(start)和尾(finish),以及可用空间的尾(end_of_storage) 可用空间:为了降低空间配置的速度成本,vector 实际配置的大小可能比客户需求的大一些(即capaci
2022-10-20
  目录