博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
STL略观——deque的中控器和迭代器
阅读量:4657 次
发布时间:2019-06-09

本文共 2417 字,大约阅读时间需要 8 分钟。

  vector 是单向开口的连续线性空间,deque 则是一种双向开口的连续线性空间,也就是说deque能够在其容器两端分别做元素的插入和删除操作,vector 

当然也可以从头尾两端进行操作,不过其头部插入或者删除元素的效率贼差,建议大家少用为妙。

  

  deque 是连续空间,但是连续却是假象,实际上 deque 是由一段一段的定量连续构成,一旦需要在 deque 的头部和尾部增加存储空间,便配置一段连续的内存空间,串接在整个 deque 的头部或者尾部。deque 的最大任务便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机访问存取的接口,避开重新配置、复制、释放的轮回,代价就是复杂的迭代器架构。deque 采用映射(map)作为主控,也就是中控器。就是一段连续的内存空间存放一大堆指针,每个指针都指向一段定量连续空间,也叫作缓冲区,缓冲区才是 deque 的主体。当我们申请对象开辟内存的时候,如果没指定缓冲区大小,默认为512bytes,注意开辟内存存的是指针,缓冲区才是存数据。

template 
class deque : protected _Deque_base<_Tp, _Alloc> { typedef _Deque_base<_Tp, _Alloc> _Base;public: // Basic types typedef _Tp value_type; typedef value_type* pointer;protected: // Internal typedefs typedef pointer* _Map_pointer; //元素的指针的指针 static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }protected:#ifdef __STL_USE_NAMESPACES using _Base::_M_map; //指向map,map是块连续空间,其中的每个元素都是一个指针(节点),指向一块缓冲区 using _Base::_M_map_size; //map内可容纳多个指针 using _Base::_M_start; using _Base::_M_finish;#endif /* __STL_USE_NAMESPACES */}

  deuqe 是分段连续空间,为了保证其连续的假象,迭代器运算子就必须好好设计,也就是 operator++ 和 operator-- 两个运算子。deque 迭代器得明白自己的任务,首先,必须能够指出缓冲区在哪里,其次它必须能够判断自己是否已经处于其所在缓冲区的边缘,一旦是,前进或者后退时就必须跳跃至下一个或者上一个缓冲区,所以 deque 应该随时掌握中控器(map)。以下是其迭代器的源代码:

template 
struct _Deque_iterator { typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } //没有继承std::iterator就必须自行撰写五个必要的迭代器相应型别 typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef _Ptr pointer; typedef _Ref reference; typedef ptrdiff_t difference_type; typedef _Tp** _Map_pointer; typedef size_t size_type; typedef _Deque_iterator _Self; _Tp* _M_cur; //迭代器缓冲区的现行元素 _Tp* _M_first; //缓冲区的头部 _Tp* _M_last; //缓冲区的尾部(包括备用空间) _Map_pointer _M_node; //中控器指针 ...}

  其中用来决定缓冲区大小的函数是 __deque_buf_size,是全局内联函数:

inline size_t __deque_buf_size(size_t __size) {
    //传入的元素大小__size小于512字节,则分配512 /__size 个空间,后期如果还需要,就开接着辟,直至512bytes,如果大于512bytes,就直接返回整个缓冲区     return __size < 512 ? size_t(512 / __size) : size_t(1);}

  以下是中控器、迭代器和缓冲区的相互关系:

  

 

转载于:https://www.cnblogs.com/Forever-Road/p/6837706.html

你可能感兴趣的文章