2

我在一本书中找到了这段代码:

void DeleteList(element *head)
{
  element *next, *deleteMe;
  deleteMe = head;
  while (deleteMe) {
    next = deleteMe->next;
    free(deleteMe);
    deleteMe = next;
  }
}

假设我们传递给函数的参数是指向列表头部的指针,为什么我们不传递对该指针的引用?

如果我们不这样做,我们不只是要删除该指针的本地副本吗?这就是我们传递引用指针的原因吗?那么被调用者得到函数内部已经完成的更改了吗?

4

5 回答 5

5

如果我们不这样做,我们不只是要删除该指针的本地副本吗?

好吧,C 中没有引用之类的东西,但我假设您的意思是指针到指针,答案是否定的。

您正在释放堆上指针指向的内存,而不是指针本身。你没有改变指针,所以副本很好。不管是不是副本,它们都指向同一个地方。

您将此与为传递给函数的变量分配一个全新的值混淆了,在这种情况下,您将需要一个指向指针的指针。例如:

// only changes the local copy
void init(some_type *foo) {
    foo = malloc(sizeof(some_type));
}

// initializes the value at *foo for the caller to see
void init(some_type **foo) {
    *foo = malloc(sizeof(some_type));
}
于 2012-04-25T17:50:11.553 回答
5

将指针传递给指针(不是指针的引用,因为 C 根本没有引用)将是一个更好的解决方案,因为您可以在删除后将其清空。正如当前定义的那样,如果调用者不小心,该函数可能会留下悬空指针。除了那个小问题,这个解决方案是有效的:调用者总是可以在NULL将列表头传递给DeleteList().

以下是我将如何用指向指针的指针重写它:

void DeleteList(element **head) {
    element *next, *deleteMe;
    deleteMe = *head;
    while (deleteMe) {
        next = deleteMe->next;
        free(deleteMe);
        deleteMe = next;
    }
    *head = NULL;
}
于 2012-04-25T17:50:28.513 回答
2

来自@dasblinkenlight 的代码可以变得更紧凑。

void DeleteList(element **head) {
    element *deleteMe;
    while ((deleteMe = *head)) {
        *head = deleteMe->next;
        free(deleteMe);
    }
}
于 2012-04-25T17:58:36.730 回答
1

调用free时,指针本身并没有改变,所以不需要通过引用传递。

于 2012-04-25T17:49:47.053 回答
1

您无需更改caller中列表头的值。

// caller
DeleteList(head);
// head points to an invalid place (the place where the list used to be)
// for convenience sake, reset to NULL
head = NULL;
于 2012-04-25T17:50:17.857 回答