STL源码剖析(四):容器(5)slist

slist概述

slist是一个单向链表,但其实现其实比list要更复杂。slist不在标准规则之内。

对于STL习惯来说,插入操作往往是在指定位置前插入,这对slist来说效率太低,因此只提供了insert_after()和erase_after()。

由于slist不方便插入和删除,其不提供push_back(),只提供push_front()。

节点

slist的节点和迭代器的设计,比list复杂很多,运用了继承机制,因此在类型转换上表现地更为复杂。

 迭代器相关代码:

struct _Slist_iterator_base
{
  typedef size_t               size_type;
  typedef ptrdiff_t            difference_type;
  typedef forward_iterator_tag iterator_category;

  _Slist_node_base* _M_node;   // 指向slist的节点

  _Slist_iterator_base(_Slist_node_base* __x) : _M_node(__x) {}
  void _M_incr() { _M_node = _M_node->_M_next; }

  // 这两个函数在遍历是会用到,两个迭代器是否相等,就看其节点是否相等
  // 节点并未重载 ==,也就是指向同一个节点才相等
  bool operator==(const _Slist_iterator_base& __x) const {
    return _M_node == __x._M_node;
  }
  bool operator!=(const _Slist_iterator_base& __x) const {
    return _M_node != __x._M_node;
  }
};

template <class _Tp, class _Ref, class _Ptr>
struct _Slist_iterator : public _Slist_iterator_base
{
  typedef _Slist_iterator<_Tp, _Tp&, _Tp*>             iterator;
  typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
  typedef _Slist_iterator<_Tp, _Ref, _Ptr>             _Self;

  typedef _Tp              value_type;
  typedef _Ptr             pointer;
  typedef _Ref             reference;
  typedef _Slist_node<_Tp> _Node;
 ......
  // 不提供 --的运算符重载,不允许后退
};

slist遍历

这里就是会用到 重载符 ==,迭代器==的判断其实就是slist_node_base的比较。

对于end()

  iterator end() { return iterator(0); }

 构建一个临时迭代器对象,同时生成一个_slist_node_base类的临时节点node(0),

对于单链表最后一个节点,其next值本身也指向_slist_node_base类的node(0)

_Node* _M_create_node(const value_type& __x) {
    _Node* __node = this->_M_get_node();
    __STL_TRY {
      construct(&__node->_M_data, __x);
      __node->_M_next = 0;
    }

有点困惑,虽然node里都只有一个值next,且next的值相同,但两个node(0)的地址不同,_slist_node_base又没重载 ==,应该是不相等啊。

侯捷老师的书上也说明了这点

 

不过这里也体现出继承的一个好处吧,next和data分离,能更简单地判断当前迭代器是不是end()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值