码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-12 09:47:24      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:源码   struct   list   stl   

此版本的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

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

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

标签:源码   struct   list   stl   

原文地址:http://blog.csdn.net/a781558066/article/details/46844625

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!