STL分析(三 list)

list

G2.9版本

list底层实现为双向循环链表,并且环状链表的尾端还有一个空白节点,这个空白节点代表迭代器指向的节点,由此可得end()指向迭代器节点,begin()指向迭代器下一个节点(IterType)((node).next)。符合STL迭代器前开后闭的原则
在这里插入图片描述
可以看到在G2.9版本中list的iterator引入了三个模板参数分别为T,T&,T
。但其可以用一个模板参数T表示,在G4.9可以看到改进

template <class T, class Alloc = alloc>
class list{
protected:
    typedef __list_node<T> list_node;
public:
    typedef list_node* link_type;
    typedef __list_iterator<T, T&, T*> iterator;
protected:
    link_type node;
.....
};
 
template <class T>
struct __list_node{
    typedef void* void_pointer;
    void_pointer prev;
    void_pointer next;
    T data;
};
 
template <class T, class Ref, class Ptr>
struct __list_iterator{
    typedef T    value_type;
    typedef Ptr  pointer;
    typedef Ref  reference;
.....
};

源码解析:

  1. G2.9中包含一个头结点link_type node,其指向链表的头结点,由于成员为指针,sizeof(list< int>)大小为4
  2. list节点类型为_list_node< T>,内置指针类型为void*,后续需要类型转换,G4.9中采用了对象本身的指针

list中的Iterator设计

template <class T, class Ref, class Ptr>
struct __list_iterator{
    typedef __list_iterator<T, Ref, Ptr>  self;
    typedef bidirectional_iterator_tag    iterator_category;//1
    typedef T                             value_type;//2
    typedef Ptr                           pointer;//3
    typedef Ref                           reference;//4
    typedef __list_node<T>*               link_type;
    typedef ptrdiff_t                     difference_type;//5
 
    link_node node;
    
    reference operator*() const { return (*node).data; }
    pointer operator->() const { return &(operator*()); }
    self& operator++()
        { node = (link_type)((*node).next); return *this; }
    self operator++(int)
        { self tmp = *this; ++*this; return tmp; }
    
    ......
};
  1. 可以看到迭代器中有typedef和操作符重载,其中5个typedef在每个迭代器中都必须具备,提供给算法iterator::value_type(元素类型),iterator::difference_type(迭代器距离,即指针之间的最大距离),iterator::iteraor_category(迭代器类型,这里为bidirectional_iterator_tag),剩余两个在STL算法中还没有用到
  2. ++重载前缀和后缀区别(1)返回引用与返回值(2)后缀有int参数
  3. ->在编译器中有特殊处理,调用ite->method();时,ite->调用operator->返回对象指针,编译器在自动添加一个->,调用对象的方法
  4. 在几乎所有迭代器中,difference_type的值都为ptrdiff_t,为内存中指针的最大寻址范围
  5. 注意:在operator++(int)函数中的self tmp = *this;实际操作时并不会唤起operator*(),因为编译器在遇见=时会唤起copy ctor创建tmp并以*this为初值,*this已经被解释为ctor的参数。++*this;时也将*this解释为operator++()的参数,在最后return *this;时调用拷贝函数,返回值。

G4.9版本

虽然也是双向循环链表,但包含了许多继承和复合关系
在这里插入图片描述
首先list继承自_List_base< _Tp, _A>,_List_base< _Tp, _A>中包含一个_List_impl< _Tp, _A>成员,这个成员中包含_List_node_base< _Tp>成员。其中_List_node_base< _Tp>内部有两个指针pre和next,代表尾后迭代器指向的空节点,即end()返回的迭代器指向节点。而普通节点类型为_List_node< _Tp>,继承自_List_node_base< _Tp>,里面多了一个数据域。

template<typename _Tp,
         typename _Alloc = std::allocator<_Tp>>
class list:protected _List_base<_Tp, _Alloc>
{
    public:typedef _List_iterator<_Tp> iterator;
......
};
 
template<typename _Tp>
struct _List_iterator
{
    typedef _Tp* pointer;
    typedef _Tp& reference;
......
};
 
struct _List_node_base
{
    _List_node_base* _M_next;
    _List_node_base* _M_prev;
};
 
template<typename _Tp>
struct _List_node
    : public _List_node_base
{
    _Tp _M_data;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值