C++链表的高级实现

本文探讨了C++开源项目中不使用STL list的原因,主要在于STL list的node未内嵌到数据结构中,与链表的局部化设计相悖。作者分享了一个在Predixy项目中优雅地实现链表的例子,通过继承使结构体内嵌链表节点,同时利用C++特性实现了插入、删除等操作。这种实现方式避免了STL list中迭代器失效的问题。
摘要由CSDN通过智能技术生成

在STL中list的底层的数据结构是链表,但是在很多c++开源项目中并没有使用STL中的list。原因是因为list中的node不是内嵌到数据结构当中的,这样就和链表的作用相违背。

链表的最大作用是他是一个局部化的结构,一个结构体只需要持有链表中的其中一个节点,就可以对这个节点本身进行插入,删除等操作,新增的结构体也同样只持有新增的节点,便可以进行链表的操作,而不需要持有整个链表。

然而std::list无法实现这个功能。这也是因为需要遵循STL中iterator的惯例,迭代器与数据是解耦的,但链表的list和数据是绑定的,所以与iterator的设计相违背,所以迭代器会遇到失效的问题,无法内嵌结构体中。

下面贴一个最近看的predixy中list链表的实现,通过继承来内嵌链表,我觉得实现的很优雅,也使用了c++中的很多特性,当然也可以去看linux内核中list的实现,原理都是类似的。

//ListNode为一个链表节点,每个结构体持有一个
//每个结构体继承ListNode,T为结构体本身,P为结构体指针(可以指定智能指针),size为节点next指针数组长度
template<class T, class P = T*, int Size = 1>
class ListNode
{
public:
    typedef P Ptr;
    ListNode()
    {
        for (int i = 0; i < Size; ++i) {
            mNext[i] = nullptr;
        }
    }
    ~ListNode()
    {
        for (int i = 0; i < Size; ++i) {
            mNext[i] = nullptr;
        }
    }
    void reset(int idx = 0)
    {
        mNext[idx] = nullptr;
    }
    void concat(T* obj, int idx = 0)
    {
        mNext[idx] = obj;
    }
    P next(int idx = 0) const
    {
        return mNext[idx];
    }
private:
    P mNext[Size];
};

//List为链表整体的结构,可以执行插入队首队尾等操作
template<class N, int Idx = 0>
class List
{
public:
	//每个结构体需要typedef一些类型,依次是结构体本身,ListNode节点
    typedef typename N::Value T;
    typedef typename N::ListNodeType Node;
    typedef typename Node::Ptr P;
public:
    List():
        mSize(0),
        mHead(nullptr),
        mTail(nullptr)
    {
    }
    ~List()
    {
        while (mSize > 0) {
            pop_front();
        }
    }
    P next(T* obj)
    {
        return node(obj)->next(Idx);
    }
    void push_back(T* obj)
    {
    	//因为结构体继承自ListNode,所以可以通过static_cast将子类转为父类再对节点进行操作,以下相同
        N* p = static_cast<N*>(obj);
        if (mTail) {
            static_cast<Node*>((T*)mTail)->concat(p, Idx);
            mTail = p;
        } else {
            mHead = mTail = p;
        }
        ++mSize;
    }
    void push_front(T* obj)
    {
        N* p = static_cast<N*>(obj);
        if (mHead) {
            node(obj)->concat(mHead, Idx);
            mHead = p;
        } else {
            mHead = mTail = p;
        }
        ++mSize;
    }
    P pop_front()
    {
        P obj = mHead;
        if (obj) {
            Node* n = node((T*)obj);
            mHead = n->next(Idx); 
            if (--mSize == 0) {
                mTail = nullptr;
            }
            n->reset(Idx);
        }
        return obj;
    }
    P front() const
    {
        return mHead;
    }
    P back() const
    {
        return mTail;
    }
    int size() const
    {
        return mSize;
    }
    bool empty() const
    {
        return mSize == 0;
    }
private:
    static Node* node(T* obj)
    {
        return static_cast<N*>(obj);
    }
private:
    int mSize;
    P mHead;
    P mTail;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值