自从几个月前我写了我的LinkedList实现后,这个问题就一直困扰着我。
这就是问题所在:我工作的环境中没有标准库(任何类型的)可用,所以我必须自己创建所有内容。
由于它是一个相当特殊的环境(即。OSDev)我的链表用例很小。然而,鉴于我是一个懒惰的人,我想使用相同的库为用户空间的程序…这将涉及扩展列表的可操作范围。
至于代码,我把它粘贴在最后(SO真的应该允许粘贴等,或者创建一个SO品牌的粘贴式的东西,或者有一些可嵌入的代码的东西,当你点击它打开一个覆盖窗口)。
这就是问题所在:我通常这样创建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++;
}
}
};
您担心的是,当您去存储它时,复杂数据类型是否会像int
一样运行。答案是,只要它有一个"复制构造函数"(一个接受类型ClassName&
并复制其中所有数据的构造函数),那么它将完全按照您的期望行事。