为什么这个列表实现比stl列表占用更多空间?

时间:2016-07-11 09:27:35

标签: c++ list templates stl iar

我正在使用IAR作为嵌入式项目的编译器。我正在尝试为列表等基本类型引入一些模板,但是创建的每个STL列表对象相对于我们当前的C样式实现增加了大约200个字节的代码大小。 我试图实现STL列表的一小部分,希望获得更小的代码占用空间,但最终比完整的STL列表更重。 我在使用模板时做了一些可怕的错误吗?

由于

P.S。请注意,代码未经测试,因此可能包含龙。

#ifndef __LINK_LIST_HPP__
#define __LINK_LIST_HPP__

#include <stdint.h>
#include <stdlib.h>

template <typename T> class list
{
private:
    struct LinkListElement
    {
        T payload;
        LinkListElement* next;
        LinkListElement* prev;
    };
public:

    class iterator
    {
        // Need access to LinkListElement struct
        friend class list;
    public:
        iterator() : m_cur_item(NULL){}

        iterator(LinkListElement* elem) : m_cur_item(elem){}

        iterator(const iterator& other) : m_cur_item(other.m_cur_item){}

        ~iterator(){}

        iterator& operator=(const iterator& other)
        {
            m_cur_item = other.m_cur_item;
            return *this;
        }

        bool operator==(const iterator& other) const
        {
            // Compare by position, ignoring the payload contents when comparing iterators.
            return  (m_cur_item->next == other.m_cur_item->next) &&
                    (m_cur_item->prev == other.m_cur_item->prev);
        }

        bool operator!=(const iterator& other) const
        {
            return !(*this == other);
        }

        // Prefix increment operator.
        iterator& operator++()
        {
            increment();
            return *this;
        }

        // Postfix increment operator.
        iterator operator++(int)
        {
            iterator copy(*this);
            increment();
            return copy;
        }

        // Prefix decrement operator.
        iterator& operator--()
        {
            decrement();
            return *this;
        }

        // Postfix decrement operator.
        iterator operator--(int)
        {
            iterator copy(*this);
            decrement();
            return copy;
        }

        T& operator*()
        {
            // Just so we won't crash, but behavior is undefined.
            if (m_cur_item == NULL)
            {
                return dummy;
            }

            return m_cur_item->payload;
        }

        T* operator->()
        {
            if (m_cur_item == NULL)
            {
                return NULL;
            }

            return &(m_cur_item->payload);
        }

    private:

        void increment()
        {
            if (m_cur_item == NULL || m_cur_item->next == NULL)
            {
                return;
            }

            m_cur_item = m_cur_item->next;
        }

        void decrement()
        {
            if (m_cur_item == NULL || m_cur_item->prev == NULL)
            {
                return;
            }

            m_cur_item = m_cur_item->prev;
        }

        LinkListElement* m_cur_item;
        static T dummy;

    };

    // Need access to internal LinkListElement pointer
    friend class iterator;

    list()
    {
        // Add sentinel to mark end of list.
        m_tail = new LinkListElement;
        m_tail->next = m_tail;
        m_tail->prev = m_tail;
        m_head = m_tail;
    }

    ~list()
    {
        // Clear entire list except for sentinel
        clear();

        // Destroy sentinel
        delete m_tail;
        m_head = NULL;
        m_tail = NULL;
    }

    T& back()
    {
        // empty list with only sentinel. Result of back() is undefined
        if (empty())
        {
            // TODO: Show some debug error
        }

        return m_tail->prev->payload;
    }

    T& front()
    {
        if (empty())
        {
            // TODO: Show some debug error
        }

        // m_head is always defined even if list is empty
        return m_head->payload;
    }

    size_t size()
    {
        return m_count;
    }

    bool empty()
    {
        // head == tail means the list is empty
        return m_head == m_tail;
    }

    iterator begin()
    {
        return iterator(m_head);
    }

    iterator end()
    {
        return iterator(m_tail);
    }

    iterator insert(iterator position, const T& payload)
    {
        // Validate position by finding it in our list
        iterator find = begin();
        while (find != end() && find != position)
        {
            ++find;
        }

        if (find == end())
        {
            // TODO: Show some debug error
            return position;
        }

        return insert_before(find.m_cur_item, payload);
    }

    void push_back(const T& payload)
    {
        insert_before(m_tail, payload);
    }

    void push_front(const T& payload)
    {
        insert_before(m_head, payload);
    }

    iterator erase(iterator position)
    {
        // Validate position by finding it in our list
        iterator find = begin();
        while (find != end() && find != position)
        {
            ++find;
        }

        if (find == end())
        {
            // TODO: Show some debug error
            return position;
        }

        return remove_at(find.m_cur_item);

    }

    //iterator erase(iterator first, iterator last);    // Implement only if needed
    void pop_back()
    {
        if (!empty())
        {
            // Don't remove the sentinel
            remove_at(m_tail->prev);
        }
    }

    void pop_front()
    {
        if (!empty())
        {
            remove_at(m_head);
        }
    }

    void remove(const T& value)
    {
        iterator iter = begin();

        while (iter != end())
        {
            iterator remove = iter++;
            if (*remove == value)
            {
                remove_at(remove.m_cur_item);
            }
        }
    }

    void clear()
    {
        while (!empty())
        {
            pop_back();
        }
    }

private:

    iterator insert_before(LinkListElement* existing, const T& payload)
    {
        // Allocate memory and save the element
        LinkListElement* new_elem = new LinkListElement;

        // For classes types (not pointer to object) this should invoke copy constructor
        new_elem->payload = payload;
        new_elem->prev = existing->prev;
        new_elem->next = existing;
        existing->prev = new_elem;
        ++m_count;

        if (existing == m_head)
        {
            m_head = new_elem;
        }

        return iterator(new_elem);
    }

    iterator remove_at(LinkListElement* to_remove)
    {
        // Allocate memory and save the element
        LinkListElement* prev = to_remove->prev;
        LinkListElement* next = to_remove->next;
        prev->next = next;
        next->prev = prev;
        --m_count;

        if (to_remove == m_head)
        {
            m_head = next;
        }

        delete to_remove;

        return iterator(prev);
    }

    LinkListElement* m_head;
    LinkListElement* m_tail;
    uint32_t         m_count;
};

template <typename T> T list<T>::iterator::dummy;

#endif

1 个答案:

答案 0 :(得分:3)

您的代码具有STL没有的各种功能和检查。所以你最终会得到更多代码是有意义的。

是的,STL具有您的代码所没有的许多功能。但是你没有使用它们中的任何一个,所以它们不会出现在你的代码中。 STL是使用模板设计的,因此您不会为不使用的内容付费。

你不太可能改善STL。如果您需要添加功能,请添加它们。你不需要重新发明轮子。