C++深入学习:STL源码剖析 (3) 从源码深入剖析list

本文深入探讨C++ STL中的list容器,分析其双向链表的节点结构、迭代器实现以及内存管理。重点讲解了list的构造、插入、删除、元素操作、迁移函数,如merge、reverse和sort。通过源码剖析,揭示了list在操作上的高效性和迭代器的稳定性。
摘要由CSDN通过智能技术生成

C++深入学习:STL源码剖析 (3) 从源码深入剖析list

vector和list是最常用的容器,vector是连续的线性空间,list则是非连续的用指针串联起的空间。因此list对于空间的利用是非常充分的,对于任意位置的插入删除操作,list是常数时间完成。

list不仅是双向链表,而且是环形双向链表,因此只需要一个指针便可以实现对整个list的迭代器的标记。为了符合STL的前闭后开的区间要求,list实现时将该指针节点指向一个置于尾端的空白节点,则该节点的前面是尾结点,该节点的后面是头结点,根据此便可以实现诸多函数。

学习list,个人觉得最大的收获是在于熟练运用指针完成相应的变换,list的部分函数也是非常经典的算法题,同时list的设计时也有诸多很巧妙的思想。

STL的list实现由三个模块组成,节点__list_node迭代器__list_iterator以及list本身

list 的节点

list是一个双向链表,因此每个节点不仅要存当前的值,还要存储两个指针用来寻找前一个节点和后一个节点。

template<class T>
struct __list_node{
   
    typedef void* void_pointer;
    void_pointer prev; //前向指针
    void_pointer next; //后向指针
    T data;   //数据
}
list的迭代器

由于list 不是vector一样节点是连续空间存储,故不能以一个普通指针作为迭代器。list的迭代器必须能够指向list 的节点,同时,还能够实现递增(指向下一个节点)、递减(指向上一个节点)、取值(取出节点的值)、成员取用(取节点的成员对象)等操作。

因此,由于list的迭代器只支持前移后移,而不支持随机访问,因此是 Bidirectional Iterators.

list和vector还有一个比较大的区别,list的插入和接合等都不会造成原有的list迭代器失效,而vector的插入操作当引起空间重配时原有的迭代器全部失效。甚者,list 的删除操作也只有被删除的那个迭代器失效,其他迭代器不受任何影响。

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的节点
    
    //构造函数
    __list_iterator(link_type x):node(x){
   }
	__list_iterator(){
   }
    __list_iterator()(const iterator& x):node(x.node){
   }
    
    //一些迭代器操作
    //重载等号和不等号
    bool operator==(const self&x) const 
    {
   
    	return node==x.node;   
    }
    bool operator!=(const self&x) const
    {
   
        return node!=x.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;
    }
    self& operator--()
    {
   
        node=(link_type)((*node).prev);
        return *this;
    }
    self operator--(int) //后-,返回原值的拷贝,然后原值--
    {
   
        self tmp=*this;
        --(*this);
        return tmp;
    }
    
}
list的数据结构

list是一个环形双向链表,因此只需要一个指针就可以完成整个链表的遍历。

template<class T,class Alloc=alloc>
class list{
   
protected:
	typedef __list_node<T> list_node;
public:
    typedef list_node* link_type
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值