放弃了std::list,自己实现了一个简单的list

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yutao52shi/article/details/79585324

原因

在项目中前人使用了std::list来做一个队列式,支持头或者尾的push操作。使用场景是视频的录制:
生产者:从摄像头采集数据,然后push_front到队列头,如果超过了最大限制,则pop_back队列尾的元素,实现丢帧操作
消费者:从队列里面back拿到桢,然后pop_back删除末尾桢。
所有的list的操作均加入了互斥锁。理论上应该是没有多线程访问的问题的。然而在线上表现却在back拿数据的时候有极少数的Crash。在拿数据前我还用empty方法判断肯定不为空的。只能认为是list内部实现可能有问题。也有可能是自己使用姿势不对吧。能力有限,看std::list的实现也看不出什么问题。在看源码的过程中,发现stl::list的size()的实现居然是O(n)复杂度,搜了下原因是为了O(1)的去实现transfer方法,便于做sort, merge等操作。基于这些问题,我决定还是自己写一个类似的数据结构,出了问题也好修复。于是就写了如下双向链表。

//
// Created by tao on 2018/3/1.
//

#pragma once

#include <atomic>
#define EXCEPTION_EMPTY_LIST 1
template<typename T>
struct Node {
    T _data;
    Node<T> *_next;
    Node<T> *_prev;
};

template<typename T>
class SimpleList {
private:
    Node<T> *m_pHead;
    Node<T> *m_pTail;
    size_t m_iSize;
public:
    SimpleList() : m_pHead(nullptr),
                   m_pTail(nullptr),
                   m_iSize(0) {}

    void push_back(T x);

    void push_front(T x);

    T back() throw(int);

    T front();

    void pop_back();

    void pop_front();

    inline int size() {
        return m_iSize;
    }

    inline bool empty() {
        return m_iSize == 0;
    }

    ~SimpleList() {
        Node<T> *cur = m_pHead;
        while (cur != nullptr) {
            Node<T> *next = cur->_next;
            delete cur;
            cur = next;
            if (cur == nullptr) {
                break;
            }
        }
    }
};

template<typename T>
void SimpleList<T>::push_back(T x) {
    Node<T> *pNewNode = new Node<T>[sizeof(Node<T>)];
    pNewNode->_data = x;
    pNewNode->_next = nullptr;
    pNewNode->_prev = nullptr;
    if (m_pHead == nullptr) {
        m_pHead = pNewNode;
        m_pHead->_prev = nullptr;
        m_pHead->_next = nullptr;
        m_pTail = m_pHead;
    } else {
        Node<T> *pCurrentNode = m_pTail;
        pCurrentNode->_next = pNewNode;
        pNewNode->_prev = pCurrentNode;
        m_pTail = pNewNode;
    }
    m_iSize++;
}

template<typename T>
T SimpleList<T>::back() throw(int) {
    if (m_pTail) {
        return m_pTail->_data;
    }
    throw EXCEPTION_EMPTY_LIST;
}

template<typename T>
T SimpleList<T>::front() {
    if (m_pHead) {
        return m_pHead->_data;
    }
    throw EXCEPTION_EMPTY_LIST;
}

template<typename T>
void SimpleList<T>::pop_back() {
    if (m_pTail) {
        if (m_pTail->_prev == nullptr) {
            delete m_pTail;
            m_pTail = nullptr;
            m_pHead = nullptr;
        } else {
            Node<T> *del = m_pTail;
            m_pTail = m_pTail->_prev;
            m_pTail->_next = nullptr;
            delete del;
            del = nullptr;
        }
        m_iSize--;
    }
}


template<typename T>
void SimpleList<T>::push_front(T x) {
    Node<T> *pNewNode = new Node<T>[sizeof(Node<T>)];
    pNewNode->_data = x;
    pNewNode->_next = m_pHead;
    pNewNode->_prev = nullptr;
    if (m_pHead != nullptr) {
        m_pHead->_prev = pNewNode;
    }
    m_pHead = pNewNode;
    if (m_pTail == nullptr) {
        m_pTail = m_pHead;
        m_pTail->_prev = nullptr;
        m_pTail->_next = nullptr;
    }
    m_iSize++;
}

template<typename T>
void SimpleList<T>::pop_front() {
    if (m_pHead != nullptr) {
        if (m_pHead->_next == nullptr) {
            delete m_pHead;
            m_pHead = nullptr;
            m_pTail = nullptr;
        } else {
            Node<T> *del = m_pHead;
            m_pHead = m_pHead->_next;
            m_pHead->_prev = nullptr;
            delete del;
            del = nullptr;
        }
        m_iSize--;
    }
}

猜你喜欢

转载自blog.csdn.net/yutao52shi/article/details/79585324
今日推荐