实现指向对象的指针的模板化双链接列表

Implementing a templated doubly linked list of pointers to objects

本文关键字:链接 列表 指针 对象 实现      更新时间:2023-10-16

我对实现双链接列表有点困惑,因为列表中的数据是指针。

我的链表类的私有部分看起来像:

private:
struct node {
node* next;
node* prev;
T* o;
};
node* first; // The pointer to the first node (NULL if none)
node* last;  // The pointer to the last node (NULL if none)
unsigned int size_;

正如你所看到的,列表中充满了指向对象的指针,而不仅仅是普通的旧对象,这让我有点困惑

以下是规范中的描述:

请注意,虽然此列表是跨所包含的类型T模板化的,但它只插入和删除指向T的指针,而不是T的实例。这确保Dlist实现知道它拥有插入的对象,如果复制了列表,它将负责复制这些对象,如果列表被销毁,它必须销毁它们

这是我目前对insertFront(T*o)的实现:

void Dlist::insertFront(T* o) {
node* insert = new node();
insert->o = new T(*o); 
insert->next = first;
insert->prev = last;
first = insert;
}

不过,这似乎是错误的。如果T没有复制构造函数怎么办?这如何确保列表中对象的唯一所有权?

我能做吗:

insert->o = o;

这似乎不安全,因为如果你有:

Object* item = new Object();
dlist.insertFront(item);
delete item;

然后,该项目也将被销毁。这是正确的吗?我的理解有偏差吗?

感谢阅读。

注意:虽然这看起来像是家庭作业,但事实并非如此。我实际上是一个java开发人员,只是通过做一个老派项目来提高我的指针技能。

当您有一个指针容器时,您有以下两种使用场景之一:

  1. 一个指向容器的指针,当删除包含结构时,容器负责删除指针。

  2. 一个指针指向容器,但由调用方拥有。调用方负责在不再需要指针时删除指针。

上面的数字1非常直接。

在数字2的情况下,预计容器的所有者(可能也是调用者)将在删除项目之前从容器中删除该项目。

我特意省略了第三个选项,它实际上是您在第一个代码示例中使用的选项。那就是分配一个新项目并复制它。我之所以省略它,是因为调用者可以这样做。

省略它的另一个原因是,您可能想要一个可以接受非指针类型的容器。通过总是使用T*而不是T来要求它是一个指针可能没有您想要的那么灵活。有时你应该强迫它成为一个指针,但我想不出对容器这样做有什么用。

如果您允许用户声明Dlist<MyClass*>而不是Dlist<MyClass>,那么该列表的所有者会隐式地意识到它正在使用指针,这迫使他们假设上面的场景编号2。

无论如何,以下是你的例子和一些评论:


1。除非有充分的理由,否则不要分配新的T项目。这个原因可能只是封装。虽然我在上面提到过你不应该这样做,但有时你可能想这样做。如果没有复制构造函数,那么你的类可能是纯旧数据。如果复制不是小事,你应该遵循"三条规则"。

void Dlist::insertFront(T* o) {
node* insert = new node();
insert->o = new T(*o);         //<-- Follow rule of three
insert->next = first;
insert->prev = last;
first = insert;
}

2。这是您通常会做的

insert->o = o;

3。插入后,您不得删除项目。将所有权传递给容器,或者在您和容器都不再需要时删除该项。

Object* item = new Object();
dlist.insertFront(item);
delete item;                     //<-- The item in the list is now invalid