[STL]<list>-P.J 版本源码简单分析

此版本的list类,很多信息都保存在内部类里面。如果抛开这些内部类,list类里面实质的成员只包括三个:

protected:
        _A allocator; //空间配置器
    _Nodeptr _Head; //list节点
    size_type _Size; //list内元素个数

抛开空间配置器不谈,_Head节点是一个_Node类型的指针

struct _Node;
    friend struct _Node;
    typedef _POINTER_X(_Node, _A) _Nodeptr;
    struct _Node {
        _Nodeptr _Next, _Prev;
        _Ty _Value;
    `
};

_POINTER_X(_Node, _A) 其实就是_Node *的宏

这里还有一个很特殊的类_Acc list里面关于节点指针访问前驱后继和值的操作,全都是由此类的成员函数实现的。这样做的好处就是让程序的可读性变得很好,整体结构变得简单

struct _Acc;
    friend struct _Acc;
    struct _Acc
    {
        typedef _Nodeptr & _Nodepref;
        typedef _Ty & _Vref;
        static _Nodepref _Next(_Nodeptr _P) //后继 引用返回
        {
            return ((_Nodepref)((*_P)._Next));
        }
        static _Nodepref _Prev(_Nodeptr _P) //前驱 引用返回
        {
            return ((_Nodepref)((*_P)._Prev));
        }
        static _Vref _Value(_Nodeptr _p)//值 引用返回

        {
            return ((_Vref)((*_p)._Value));
)}
};

我们来看看申请节点函数_Buynode和插入函数的实现,体会一下用_Acc封装这三个函数后,代码结构上优化。

_Nodeptr _Buynode(_Nodeptr _Narg = 0, _Nodeptr _Parg = 0)
    {
        _Nodeptr _S = (_Nodeptr)malloc(sizeof(_Node) * 1);
        _Acc::_Next(_S) = _Narg != 0 ? _Narg : _S;
        _Acc::_Prev(_S) = _Parg != 0 ? _Parg : _S;
        return _S;
    }

在申请节点的同时,可以初始化节点的前驱,后继

void insert(iterator _P, const _Ty &_X = _Ty())
    {
        _Nodeptr _S = _P.Mynode();
        _Acc::_Prev(_S) = _Buynode(_S, _Acc::_Prev(_S));
        _S = _Acc::_Prev(_S);
        _Acc::_Next(_Acc::_Prev(_S)) = _S;
        _Acc::_Value(_S) = _X;
        _Size++;
    }

我觉得,这样的代码在可读性上,比下面的容易多了,大家可以感受下区别

void insert(iterator _P, const _Ty &_X = _Ty())
    {
        _Nodeptr _S = _P.Mynode();
        S->Prev = _Buynode(_S, S->Prev
        _S = S->Prev
        S->Prev->Next = _S;
        _S->Value= _X;
        _Size++;
    }

内部类里面还有2个比较特殊的类,就是迭代器iterator和const_iterator

这两个类有什么区别呢?

如果你在使用一个迭代器的时候,你只想遍历元素的_Value域,而不需要改变其值,可是这时候有个问题就是,只在iterator 前面加上const 那么并不能解决这个问题,此时的迭代器变成了常迭代器,只能指向一个节点,而且要在初始化的时候赋值,这样的迭代器并没有什么卵用。所以,在list的内部,定义了一个const_iterator的类,他的作用就是解决上面这个问题的

这两个类的成员只有一个,节点的指针

他的成员函数,就是一堆重载运算符,使其能像普通的指针那样,访问元素,我们拿iterator举例

friend class iterator;
    class iterator : public const_iterator {
    public:
        _Tptr operator->() const
            {return (&**this); }
    //从有向左,这里第一个*this理解成一个迭代器的实例,对他解引用实际上是调用了其重载运算符*取其节点_Value,然后在取地址返回
        iterator& operator++()
            {_Ptr = _Acc::_Next(_Ptr);
            return (*this); }
        iterator operator++(int)
            {iterator _Tmp = *this;
            ++*this;
            return (_Tmp); }
    //返回++*this 前的*this
        };

最后附上自己实现的去掉空间配置器的代码

#ifndef _LIST_H_
#define _LIST_H_

template <class _Ty>
class mylist
{
private:
    struct _Node;
    friend struct _Node;
    typedef _Node * _Nodeptr;
    struct _Node
    {
        _Nodeptr _Prev, _Next;
        _Ty _Value;
    };
    struct _Acc;
    friend struct _Acc;
    struct _Acc
    {
        typedef _Nodeptr & _Nodepref;
        typedef _Ty & _Vref;
        static _Nodepref _Next(_Nodeptr _P)
        {
            return ((_Nodepref)((*_P)._Next));
        }
        static _Nodepref _Prev(_Nodeptr _P)
        {
            return ((_Nodepref)((*_P)._Prev));
        }
        static _Vref _Value(_Nodeptr _p)
        {
            return ((_Vref)((*_p)._Value));
        }
    };
public:
    typedef mylist<_Ty> _Myt;
    typedef unsigned int size_type;
    //typedef _PDFT difference_type;
    typedef _Ty * pointer;
    typedef const _Ty  *const_pointer;
    typedef _Ty & reference;
    typedef const _Ty & const_reference;
    typedef _Ty value_type;

    class iterator;
    friend class iterator;
    class iterator
    {
    public:
        iterator()
        {}
        iterator(_Nodeptr _P) :_Ptr(_P)
        {}
        iterator(iterator &_X) :_Ptr(_X._Ptr)
        {}
        reference operator*()
        {
            return (_Acc::_Value(_Ptr));
        }
        pointer operator->()
        {
            return &**this;//
        }
        iterator& operator++()
        {
            _Ptr = _Acc::_Next(_Ptr);
            return *this;//对象
        }
        iterator operator++(int)
        {
            iterator Tmp = *this;
            ++*this;
            return Tmp;
        }
        iterator& operator--()
        {
            _Ptr = _Acc::_Prev(_Ptr);
            return *this;//对象
        }
        iterator operator--(int)
        {
            iterator Tmp = *this;
            --*this;
            return Tmp;
        }
        bool operator==(iterator &_X)
        {
            return _Ptr == _X._Ptr;
        }
        bool operator!=(iterator &_X)
        {
            return _Ptr != _X._Ptr;
        }
        _Nodeptr Mynode()const
        {
            return _Ptr;
        }
    protected:
        _Nodeptr _Ptr;
    };
    typedef iterator _It;
public:
    mylist() :_Head(_Buynode()),_Size(0)
    {}
    mylist(size_type _N, const _Ty &_X=_Ty()) :_Head(_Buynode()), _Size(0)
    {
        insert(end(), _N, _X);
    }
    mylist(_Myt& _X) :_Head(_Buynode()), _Size(0) //
    {
        insert(end(), _X.begin(), _X.end());
    }
    mylist(_It _F, _It _L) :_Head(_Buynode()), _Size(0)
    {
        insert(end(), _F, _L);
    }
    mylist(const _Ty *_F, const _Ty *_L) :_Head(_Buynode()), _Size(0)
    {
        insert(end(), _F, _L);
    }
    ~mylist()
    {
        erase(begin(), end());
        _Freenode(_Head);
        _Head = 0;     //防止野指针
        _Size = 0;
    }
    iterator begin()
    {
        return (iterator(_Acc::_Next(_Head)));
    }
    iterator end()
    {
        return iterator(_Head);
    }
    size_type size()
    {
        return _Size
    };
    bool empty()
    {
        return _Size == 0;
    }
    void clear()
    {
        erase(begin(), end());
    }
    void push_back(const _Ty &_X = _Ty())
    {
        insert(end(),_X);
    }
    void push_front(const _Ty &_X = _Ty())
    {
        insert(begin(),_X);
    }
    void pop_front()
    {
        erase(begin());
    }
    void pop_back()
    {
        //erase(end())
        erase(--end());//
    }
    iterator erase(iterator _P)
    {
        _Nodeptr _S = (_P++).Mynode();
        _Acc::_Next(_Acc::_Prev(_S)) = _Acc::_Next(_S);
        _Acc::_Prev(_Acc::_Next(_S)) = _Acc::_Prev(_S);
        _Freenode(_S);
        --_Size;
        return _P;
    }
    void erase(iterator _F, iterator _L)
    {
        /*for (; _F != _L; _F++)
        {
        erase(_F);
        }*/
        while (_F != _L)
        {
            erase(_F++);
        }
    }
    void insert(iterator _P, const _Ty &_X = _Ty())
    {
        _Nodeptr _S = _P.Mynode();
        _Acc::_Prev(_S) = _Buynode(_S, _Acc::_Prev(_S));
        _S = _Acc::_Prev(_S);
        _Acc::_Next(_Acc::_Prev(_S)) = _S;
        _Acc::_Value(_S) = _X;
        _Size++;
    }
    void insert(iterator _P, size_type _N,const _Ty&_X = _X())  //在_P 前插入_N个_X
    {
        for (; _N; _N--)
        {
            insert(_P, _X);
        }
    }

    void insert(iterator _P, _It _F, _It _L)
    {
        for (; _F != _L;_F++)
        {
            insert(_P, *_F);
        }
    }
    void insert(iterator _P, const _Ty *_F, const _Ty *_L)
    {
        for(; _F != _L;_F++)
        {
            insert(_P, *_F);
        }
    }
    void assign(size_type _N, const _Ty& _X)
    {
        erase(begin(), end());
        insert(end(), _N, _X);
    }
    void assign(iterator _F, iterator _L)
    {
        erase(begin(), end());
        insert(end(), _F, _L);
    }
    void splice(iterator _P,_Myt& _X)
    {
        if (!_X.empty())
        {
            _Splice(_P, _X, _X.begin(), _X.end());
            _Size += _X._Size;
            _X._Size = 0;
        }
    }
    void splice(iterator _P, _Myt& _X, iterator _F)
    {
        iterator _L = _F;
        if (_P != _L && _P != ++_L)
        {
            _Splice(_P, _X, _F, _L);
            _Size++;
            _X._Size--;
        }
    }
    void splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
    {
        if (_F != _L)
        {
            if (&_X != this)
            {
                int _N = 0;
                _Distance(_F, _L, _N);
                _Size += _N;
                _X._Size -= _N;
            }
            _Splice(_P, _X, _F, _L);
        }
    }
    void swap(_Myt& _X)
    {
        iterator _L = begin();
        splice(_L, _X);
        _X.splice(_X.begin(), *this, _L, end());
    }
    friend void swap(_Myt& _X, _Myt& _Y)
    {
        _X.swap(_Y);
    }
    void remove(const _Ty& _V)
    {
        iterator _F = begin();
        while (_F != end())
        {
            if (*_F == _V)
                erase(_F++);
            else
                ++_F;
        }
    }
    void unique()
    {
        iterator _F = begin();
        iterator _M ;
        for (_M = _F; ++_M != end(); _M = _F)
        {
            if (*_F == *_M)
                erase(_M);
            else
                _F = _M;
        }
    }
    void reverse()
    {
        if (_Size >= 2)
        {
            iterator _F = ++begin();
            iterator _M;
            for (; _F != end();)
            {
                _M = _F;
                splice(begin(), *this, _M, ++_F);
            }
        }
    }
    void merge(_Myt& _X)
    {
        if (&_X != this)
        {
            iterator _F1= begin(), _L1 = end();
            iterator _F2 = _X.begin(), _L2 = _X.end();
            while (_F1 != _L1 && _F2 != _L2)
            {
                if (*_F2 < *_F1)
                {
                    iterator _M = _F2++;
                    splice(_F1, _X, _M, _F2);
                }
                else
                    _F1++;
            }
            if (_F2 != _L2)
                splice(_L1, _X, _F2, _L2);
            _Size += _X._Size;
            _X._Size = 0;
        }
    }

protected:
    _Nodeptr _Buynode(_Nodeptr _Narg = 0, _Nodeptr _Parg = 0)
    {
        _Nodeptr _S = (_Nodeptr)malloc(sizeof(_Node) * 1);
        _Acc::_Next(_S) = _Narg != 0 ? _Narg : _S;
        _Acc::_Prev(_S) = _Parg != 0 ? _Parg : _S;
        return _S;
    }
    void _Freenode(_Nodeptr _P)
    {
        free(_P);
    }
    void _Splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
    {
        insert(_P, _F, _L);
        _X.erase(_F, _L);
    }
    void _Distance(iterator _F, iterator _L, int &_N)
    {
        while (_F != _L)
        {
            _N++;
            _F++;
        }
    }
    _Nodeptr _Head;
    size_type _Size;

};
#endif

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-12 12:12:18

[STL]<list>-P.J 版本源码简单分析的相关文章

Spring各版本源码下载

spring framework 各版本源码下载地址 现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-projects/spring-framework/tags可以选择需要的版本进行下载. 感谢网友 xiyuan1999 在csdn上提供的此下载地址.

可解决由于IIS、VS低版本源码 兼容性问题。

安装完 Internet Information Services和 Web 管理工具 后,重启VS,以管理员身份打开,同时 选择源码--属性--安全--添加 everyone 所有权限,配置IIS,即可解决由于IIS.VS低版本源码 兼容性问题. 解决方法: 重新启动时  右键 选以管理员身份运行 那是兼容性还没配置把 控制面板-程序和功能 打开或关闭 Windows 功能 找到这个Internet Information Services 展开Web 管理工具 安装完 Internet In

kafka 0.8.1 新producer 源码简单分析

1 背景 最近由于项目需要,需要使用kafka的producer.但是对于c++,kafka官方并没有很好的支持. 在kafka官网上可以找到0.8.x的客户端.可以使用的客户端有C版本客户端,此客户端虽然目前看来还较为活跃,但是代码问题还是较多的,而且对于c++的支持并不是很好. 还有c++版本,虽然该客户端是按照c++的思路设计,但是最近更新时间为2013年12月19日,已经很久没有更新了. 从官方了解到,kafka作者对于现有的producer和consumer的设计是不太满意的.他们打算

FFmpeg源码简单分析:libswscale的sws_scale()

===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 - 编码 [通用] FFmpeg 源码简单分析:av_register_all() FFmpeg 源码简单分析:avcodec_register_all() FFmpeg 源码简单分析:内存的分配和释放(av_malloc().av_free()等) FFmpeg 源码简单分析:常

Android属性动画AnimatorSet源码简单分析

跟上之前的两篇文章 Android属性动画ValueAnimator源码简单分析 Android属性动画ObjectAnimator源码简单分析 继续看AnimatorSet源码的大概过程. AnimatorSet 提供了一种把多个动画放到一起,按照某种特定的顺序来播放,比如一个接一个的播放或者多个动画一起播放. AnimatorSet简单使用随便举一个最简单的例子 //AnimatorSet AnimatorSet animSet = new AnimatorSet(); ObjectAnim

netty 源码简单分析一

周末简单看了下netty5的源码,只看懂了个大概,记录下成果,方便下次再看的时候回忆. 上服务端代码: public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.grou

Javac源码简单分析之解析和填充符号表

一.说明 符号表是由一组符号地址和符号信息构成的表格.符号表中所登记的信息在编译的不同阶段都要用到,在语义分析(后面的步骤)中,符号表所登记的内容将用于语义检查和产生中间代码,在目标代码生成阶段,党对符号名进行地址分配时,符号表是地址分配的依据. 二.主要的类与方法 解析和填充符号表这个过程主要由com.sun.tools.javac.comp.Entry及com.sun.tools.javac.comp.MemberEnter两个类来实现的. com.sun.tools.javac.comp.

Javac源码简单分析之Javac简单介绍

一.简单介绍 javac 是java语言编程编译器.javac工具读由java语言编写的类和接口的定义,并将它们编译成字节代码的class文件. 二.源码获取 OpenJDK6源码:http://download.java.net/openjdk/jdk6/ Javac的源码就在OpenJDK源码里面. 或者在CSDN下载:http://download.csdn.net/detail/p_3er/7383741 三.Javac的包 Javac的公共入口点是com.sun.tools.javac

FFmpeg源码简单分析:结构体成员管理系统-AVOption

===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 - 编码 [通用] FFmpeg 源码简单分析:av_register_all() FFmpeg 源码简单分析:avcodec_register_all() FFmpeg 源码简单分析:内存的分配和释放(av_malloc().av_free()等) FFmpeg 源码简单分析:常