2

本でこのコードを見つけました:

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

関数に渡す引数がリストの先頭へのポインターであると仮定すると、なぜそのポインターへの参照を渡さないのでしょうか?

そうしないと、そのポインターのローカル コピーを削除するだけではないでしょうか。それが参照ポインタを正しく渡す理由です。呼び出し先は、関数内で行われた変更を取得しますか?

4

5 に答える 5

5

ポインターへのポインター (C には参照がまったくないため、ポインターへの参照ではない) を渡すことは、削除後に null にすることができるため、より良い解決策になります。現在定義されているため、呼び出し元が注意しないと、関数はダングリング ポインターを残す可能性があります。その小さな問題を除けば、この解決策は有効です。呼び出し元は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 に答える
5

そうしないと、そのポインターのローカル コピーを削除するだけではないでしょうか。

C には参照などというものはありません。

ポインタ自体ではなく、ポインタが指しているメモリをヒープ上で解放しています。pointerを変更していないので、コピーで問題ありません。コピーかどうかに関係なく、同じ場所を指しています。

これを、関数に渡された変数にまったく新しい値を代入することと混同しています。その場合、ポインターからポインターを取得する必要があります。例えば:

// 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 に答える
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のリストの head の値を変更する必要はありません。

// 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 に答える