C++STL 体系结构与内核分析(侯捷)——课程笔记(四)

本文深入分析了G2.9和G4.9版本中list的源码实现,详细解释了双向循环链表结构、迭代器设计以及节点类型的演变。对比了两个版本在节点指针类型、迭代器模板参数上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本部分的内容包括list的源码分析。

一、G2.9版本的list源码

list底层实现为双向循环链表,并且环状链表的尾端还有一个空白节点,代表尾后迭代器指向的节点,用以符合STL前闭后开的原则,其示意图如下:

G2.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的list包含一个头指针,指向链表中的头结点,所以对list求sizeof的大小为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;
    typedef T                             value_type;
    typedef Ptr                           pointer;
    typedef Ref                           reference;
    typedef __list_node<T>*               link_type;
    typedef ptrdiff_t                     difference_type;

    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和操作符重载(后面会讲几乎所有迭代器都一定要有这五个typedef)。

2. 注意++的前置版本和后置版本的区别,参数列表,返回类型等

3. 对于符号->的重载编译器有一些特殊处理(这里不太理解),如下图所示:

三、G4.9中的list

虽然也是双向循环链表,但是和G2.9的设计略有不同。一个list内包含一个_List_node_base<_Tp>,其内是两个指针prev和next,代表的是尾后迭代器指向的那个空节点,而普通节点类型为_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;
};

可以看出节点的指针类型变为了精确类型,并且iterator的模板参数由三个变成了一个,更加容易理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值