【问题标题】:Making Custom Linked List work with PODs使自定义链表与 POD 一起使用
【发布时间】:2014-03-14 16:20:13
【问题描述】:

自从几个月前我编写了 LinkedList 实现以来,这一直困扰着我。

这就是问题所在:我在一个标准库(任何类型的)不可用的环境中工作,所以我必须自己创建所有东西。

因为它是一个相当专业的环境(即 OSDev),所以我的链表的用例很小。但是,鉴于我是一个懒人,我想将相同的库用于用户空间程序......这将涉及扩大列表的可操作范围。

至于代码,我已经把它贴在最后了(所以真的应该允许 pastebin 等,或者创建一个 SO 品牌的 pastebin 式的东西,或者有某种可嵌入的代码东西来打开一个覆盖窗口当你点击它时)。

这就是问题所在:我通常这样创建 LinkedList:

LinkedList<PCIDevice>* list = new LinkedList<PCIDevice>();

然后,例如 list->Front() 将返回 PCIDevice*,或指向 PCIDevice 的指针。这通常对我有用,因为我的大部分对象都是使用 new/delete 手动分配的。

不幸的是,如果我尝试类似的事情

LinkedList<int>* list = new LinkedList<int>();
list->InsertFront(10);

InsertFront 调用需要一个 int*。这个问题困扰了我很久,我该怎么办?

我认为我必须按照以下方式做一些事情

LinkedList<PCIDevice*>* list = new LinkedList<PCIDevice*>();

要获得指向 PCIDevice 的指针列表...但我仍然对非指针复杂类以及返回值和方法调用参数有点困惑...所以如果有人也能解释一下,它会不胜感激。

代码:

template <class data>
class LinkedList
{
    private:
        template <typename obj>
        class SingleNode
        {
            public:
                SingleNode(obj* o = 0, SingleNode<obj>* n = 0)
                {
                    this->object = (obj*)o;
                    this->next = n;
                    this->magic = 0xBEEFBEEFBEEFBEEF;
                }

                SingleNode<obj>* next;
                obj* object;
                uint64_t magic;
        };

        uint64_t length;
        uint64_t size;
        SingleNode<data>* head;
        SingleNode<data>* tail;


        SingleNode<data>* Traverse(uint64_t i) const
        {
            SingleNode<data>* h = this->head;
            // if(i >= this->length)
            //  HALT("List index out of bounds.");

            if(this->length == 1 || i == 0)
            {
                return this->head;
            }
            else if(this->length == 2 && i == 1)
            {
                return this->tail;
            }
            for(uint64_t l = 0; l < i; l++)
            {
                h = h->next;
            }
            return h;
        }





    public:
        // this needs to be already allocated; give a head pointer.
        LinkedList()
        {
            this->head = 0;
            this->tail = 0;
            this->length = 0;
            this->size = sizeof(data);
        }
        ~LinkedList()
        {
            // delete all nodes
            for(uint64_t i = 0, m = this->length; i < m; i++)
            {
                SingleNode<data>* s = this->head;
                this->head = this->head->next;

                delete s;
            }
        }


        uint64_t Size(){ return this->length; }
        bool IsEmpty(){ return this->length == 0; }
        data* Get(uint64_t i) const
        {
            if(i >= this->length)
            {
                asm volatile("xchg %bx, %bx");
            }

            if(this->length == 1 || i == 0)
            {
                return this->head->object;
            }
            else if(i == this->length - 1)
            {
                return this->tail->object;
            }

            return this->Traverse(i)->object;
        }






        void InsertFront(data* obj)
        {
            SingleNode<data>* f = new SingleNode<data>(obj, this->head);


            if(this->IsEmpty())
            {
                this->head = f;
                this->tail = f;
            }
            else
            {
                this->head = f;
            }

            this->length++;
        }

        void InsertBack(data* obj)
        {
            SingleNode<data>* f = new SingleNode<data>(obj, 0);

            if(this->IsEmpty())
            {
                this->head = f;
            }
            else
            {
                this->tail->next = f;
            }

            this->tail = f;
            this->length++;
        }

        void AddAll(LinkedList<data>* l)
        {
            for(uint64_t i = 0; i < l->Size(); i++)
            {
                this->InsertBack(l->Get(i));
            }
        }

        data* RemoveFront()
        {
            // if(this->head == 0)
            //  HALT("Removing from empty list");

            data* obj = this->head->object;
            SingleNode<data>* old_head = this->head;

            if(this->length == 1)
            {
                this->head = 0;
                this->tail = 0;
            }
            else
            {
                this->head = this->head->next;
            }

            delete old_head;
            this->length--;
            return obj;
        }

        data* RemoveBack()
        {
            // if(this->tail == 0)
            //  HALT("Removing from empty list!");

            SingleNode<data>* old_tail = this->tail;
            data* obj = this->tail->object;


            if(this->length == 1)
            {
                this->head = 0;
                this->tail = 0;
            }
            else
            {
                SingleNode<data>* kr = this->head;
                while(kr->next != this->tail)
                    kr = kr->next;

                kr->next = 0;
                this->tail = kr;
            }

            delete old_tail;
            this->length--;
            return obj;
        }

        data* Back()
        {
            return this->tail->object;
        }

        data* Front()
        {
            return this->head->object;
        }

        void Clear()
        {
            for(uint64_t m = 0, g = this->length; m < g; m++)
            {
                this->RemoveFront();
            }
        }

        int64_t IndexOf(data* p)
        {
            for(int64_t d = 0; (uint64_t)d < this->length; d++)
            {
                if(p == this->Get((uint64_t)d))
                    return d;
            }

            return -1;
        }

        data* RemoveAt(uint64_t i)
        {
            // if(i >= this->length)
            //  HALT("List index out of bounds");

            if(i == 0)
                return this->RemoveFront();

            if(i == this->length - 1)
                return this->RemoveBack();


            data* ret = this->Get(i);
            SingleNode<data>* k = this->Traverse(i);
            SingleNode<data>* p = this->Traverse(i - 1);

            p->next = k->next;
            delete k;
            this->length--;

            return ret;
        }

        void InsertAt(uint64_t i, data* d)
        {
            if(i >= this->length)
                this->InsertBack(d);

            else if(i == 0)
                this->InsertFront(d);

            else
            {
                SingleNode<data>* p = this->Traverse(i - 1);
                SingleNode<data>* t = this->Traverse(i);
                SingleNode<data>* n = this->Traverse(i + 1);
                p->next = new SingleNode<data>(d, t);
                t->next = n;
                this->length++;
            }
        }
};

【问题讨论】:

    标签: c++ pointers reference linked-list


    【解决方案1】:

    您担心的是当您去存储复杂数据类型时,它是否会表现得像int。答案是,只要它有一个“复制构造函数”(一个接受 ClassName&amp; 类型并复制其中所有数据的构造函数),它就会完全按照您的预期行事。

    【讨论】:

    • 那么我需要做些什么改变呢?我应该将所有 T* 更改为简单的 T 吗?还是 T&?
    • @zhiayang 是的,把它们都变成 T 并且只要求 T 有一个复制构造函数。
    • 是的,设法让它工作。虽然 Front() 和 Back() 之类的东西不应该返回引用吗?
    • @zhiayang 是的,就像他们在 STL 中所做的那样
    猜你喜欢
    • 2017-07-27
    • 2017-03-28
    • 2018-11-14
    • 2016-11-04
    • 2011-03-01
    • 2020-11-10
    • 2017-09-30
    • 2013-06-13
    • 2017-07-04
    相关资源
    最近更新 更多