C++ STL中容器的数据成员和迭代器总结

记录STL容器中的数据成员和迭代器结构。(配合大佬源码分析食用)
在这里插入图片描述

1、list容器

先给出大佬的详细源码分析https://blog.csdn.net/qq_41453285/article/details/103571246

1.1 list数据成员

在这里插入图片描述

  • 关于list容器的数据成员和迭代器如上图所示,因此可以得到list本身大小为4字节(__list_node*
  • list的每个节点是一个结构体。以下是list的节点(node)结构:
template <class T>
struct __list_node {
    typedef void* void_pointer;
    void_pointer prev; //类型为void*。其实可设为__list_node<T>*
    void_pointer next;
    T data;
};

1.2 list容器迭代器

list迭代器是另外定义的结构体,不像vector容器的迭代器为原生指标,自增、自减和成员取用等操作需要自己定义。其示意图如下:
在这里插入图片描述

  • 迭代器的数据成员就一个节点指针,代码如下:

template<class T, class Ref, class Ptr>
struct list_iterator {
    typedef list_iterator<T, T&, T*> iterator;
    typedef list_iterator<T, Ref, Ptr> self;
    
    typedef bidirectional_iterator_tag iterator_category;
    typedef T value_type;
    typedef Ptr pointer;
    typedef Ref reference;
    typedef list_node<T>* link_type;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
 
    link_type node; / 迭代器内部当然要有一个原生指标,指向list的节点
};

2、vector容器

这里是大佬的源码分析https://blog.csdn.net/qq_41453285/article/details/103565158

  • vector的数据成员和迭代器是:

template <class T, class Alloc = alloc>
class vector {
...
public:
    typedef T value_type;
    typedef value_type* iterator; //vector的迭代器是原生指标
  
protected:
    iterator start; //表示目前使用空间的头
    iterator finish; //表示目前使用空间的尾
    iterator end_of_storage; //表示目前可用空间的尾
    ...
};
  • 所以vector容器本身是12字节(三个value_type指针)

  • vector容器的示意图如下:

在这里插入图片描述

3、deque容器

贴上大佬的源码分析https://blog.csdn.net/qq_41453285/article/details/103614247

3.1 deque容器的数据成员

  • 数据成员16字节(三个指针,一个unsigned int 4字节)

template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
public: //Basic types
    typedef T value_type;
    typedef value_type* pointer;
    typedef __deque_iterator<T,T&,T*,BufSiz> iterator;
    ...
 
protected: //Internal typedefs
    //元素的指针的指针(pointer of pointer of T)
    typedef pointer* map_pointer;
 
protected: // Data members
	iterator start;
	iterator finish;
    map_pointer map;    //指向 map,map是块连续空间,其内的每个元素
                        //都是一个指标(称为节点),指向一块缓冲区
    size_type map_size; //map内可容纳多少指针
    ...

在这里插入图片描述

3.2 deque容器的迭代器

deque是分段连续空间。维护其“整体连续”假象的任务,着落在迭代器的operator++ 和 operator-- 两个运算符身上。
deque的迭代器应该具有以下功能:

  • 首先,它必须能够指出分段连续空间(亦即缓冲区)在哪里
  • 其次它必须能够判断自己是否已经处于其所在缓冲区的边缘,如果是,一旦前进或后退时就必须跳跃至下一个或上一个缓冲区
  • 为了能够正确跳跃,deque必须随时掌握管控中心(map)

在这里插入图片描述

  • cur:当前迭代器所指的元素
  • first:迭代器当前所指的缓冲区区间的头
  • last:迭代器当前所指的缓冲区区间的尾
  • node:指向deque管控器中的一个指针。用来指针当前迭代器所指的缓冲区归管控器中的哪一个指针所管理
    在这里插入图片描述
    stack和queue是对deque的功能做出相应限制的一个适配器。

4、红黑树

直接看大佬的分析吧(太强了)https://blog.csdn.net/qq_41453285/article/details/103645839

4.1 红黑树数据成员

在这里插入图片描述

  • value是pair<key,data>
  • KeyofValue是从value中“抽取”出key的函数体
  • Compare是比较key值大小的函数体,用于排序
  • RB-tree只有三个数据成员,size_type是4个字节,header是指针 4字节,Compare是函数体理论上0字节,但在实际中分配了1字节,所以总共9字节,但需要对齐成4的倍数,所以RB-tree是12字节

4.2 红黑树的迭代器

在这里插入图片描述

  • RB-tree迭代器属于双向迭代器,但不具备随机定位能力,其提领操作和成员访问操作与list十分类似
  • 注意:
    RB-tree迭代器的前进操作operator++()调用的是基类中的increment()函数
    RB-tree迭代器的后退操作operator–()调用的是基类中的decrement()函数
  • 前进或后退的行为依据二叉搜索树的节点排列规则,再加上实现上的某些特殊技巧

set/multiset、map/multimap的底层实现是红黑树

5、hash table

膜拜大佬https://blog.csdn.net/qq_41453285/article/details/104260053

4.1 成员函数

  • 下面就是哈希表的结构,其内部是以vector实现的
  • 模板参数比较多,包括:
    Value:节点的实值类型
    Key:节点的键值类型
    HashFcn:hash function的函数类型
    ExtractKey:从节点取出键值的方法(函数或仿函数)
    EqualKey:判断键值相同与否的方法(函数或仿函数)
    Alloc:空间配置器。缺省使用std::alloc
    在这里插入图片描述

4.2 迭代器

如上图,迭代器数据成员有:

_Node* _M_cur; //迭代器目前所指节点
_Hashtable* _M_ht;//保持对容器的连结关系(因为可能需要从bucket跳到bucket)
  • 迭代器没有后退操作(operator–),也没有定义所谓的你想迭代器(reverse iterator)
  • 迭代器前进操作(operator++):
    其前进操作时首先尝试从目前所知的节点出发,前进一个位置(节点),由于节点被安置于list内,所以利用节点的next指针即可轻易达到进行的目的
    如果目前节点正巧是list的尾端,就跳到下一个bucket内,跳过之后指向下一个list的头节点
  • 下面是operator++的定义
template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
          class _All>
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
{
  const _Node* __old = _M_cur;
  _M_cur = _M_cur->_M_next; //如果存在,就是它,否则进入if
  if (!_M_cur) {
    //根据元素值,定位出下一个bucket。其起头处就是我们的目的地
    size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
    while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())//注意operator++
      _M_cur = _M_ht->_M_buckets[__bucket];
  }
  return *this;
}
 
template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
          class _All>
inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
{
  iterator __tmp = *this;
  ++*this; //调用operator++()
  return __tmp;
}

hash table是unordered_xxx的底层实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值