簡體   English   中英

函數何時必須通過引用接收自變量以更改自變量?

[英]When must a function receive an argument by reference in order to change something about the argument?

我的問題與以下代碼有關(請注意,我在此處詢問了有關代碼不同區域的相關問題):

#include <stdio.h>
#include <stdlib.h>

struct node
{
    int v;
    struct node * left;
    struct node * right;
};

typedef struct node Node;

struct bst
{
    Node * root;
};

typedef struct bst BST;

BST * bst_insert(BST * tree, int newValue);
Node * bst_insert_node(Node * node, int newValue);
void bst_traverseInOrder(BST * tree); 
void bst_traverseInOrderNode(Node * node);

int main(void)
{
    BST * t = NULL;

    t = bst_insert(t, 5);
    bst_insert(t, 8);
    bst_insert(t, 6);
    bst_insert(t, 3);
    bst_insert(t, 12);

    bst_traverseInOrder(t);

    return 0;
}

BST * bst_insert(BST * tree, int newValue)
{
    if (tree == NULL)
    {
        tree = (BST *) malloc(sizeof(BST));
        tree->root = (Node *) malloc(sizeof(Node));
        tree->root->v = newValue;
        tree->root->left = NULL;
        tree->root->right = NULL;

        return tree;
    }

    tree->root = bst_insert_node(tree->root, newValue);
    return tree;
}

Node * bst_insert_node(Node * node, int newValue)
{
    if (node == NULL)
    {
        Node * new = (Node *) malloc(sizeof(Node));
        new->v = newValue;
        new->left = NULL;
        new->right = NULL;
        return new;
    }
    else if (newValue < node->v)
        node->left = bst_insert_node(node->left, newValue);
    else
        node->right = bst_insert_node(node->right, newValue);

    return node;
}

void bst_traverseInOrder(BST * tree)
{
    if (tree == NULL)
        return;
    else
    {
        bst_traverseInOrderNode(tree->root);
        printf("\n");
    }
}

void bst_traverseInOrderNode(Node * node)
{
    if (node == NULL)
        return;
    else
    {
        bst_traverseInOrderNode(node->left);
        printf("%d ", node->v);
        bst_traverseInOrderNode(node->right);
    }
}

特別是,看來我必須重新分配tbst-insert(t, 5)main以實際修改t本身,因為bst_insert不采取BST *參照,但只能通過值(例如所以它永遠不能真正更改BST *本身)。 但是,稍后,當創建了BST時,我可以簡單地聲明bst_insert(t, 8) ,這將更改t本身(例如,更改t->root->left ),即使它沒有接收到t作為參數參考。 有人可以在這里給我解釋一下區別嗎? 非常感謝!

“ ...因為bst_insert不會通過引用來獲取BST *,而僅通過值來獲取。”您使用了錯誤的術語,這可能是由於對下面概念的不清楚理解。

C沒有按引用傳遞 :函數的每個參數都按值傳遞。 傳遞值意味着在進行函數調用時,將復制參數,並且函數的相應參數將獲得該副本。 因此,在函數內部,您可以使用參數的副本。

相反,某些語言(特別是C ++,但不是C )可以通過引用傳遞參數。 這意味着函數中的相應參數將成為參數的別名 ,即可以用作同一對象的替代名稱。 在這種情況下,您使用函數內部的別名對對象進行的任何修改都會影響函數“外部”的參數。

在C語言中,您可以使用指針作為函數參數來更接近傳遞引用的行為。 如果傳遞指針 (即對象地址),則可以在函數內部使用它來間接更改指針指向的對象。

有人將此稱為“技巧” 傳遞指針 (或“ 呼叫 傳遞 指針” ),但IMO將此術語誤導給不了解實際底層機制的初學者。 確實,這根本不是一種新機制,它只是應用於指針值的按值傳遞! 實際上,您對指針本身 (相對於所指向的對象)所做的任何更改都是本地的,即不會影響您在調用中傳遞的實際指針。

不同之處在於,在第一次調用中(當tNULL ),函數bst_insert更改了指針t本身(它使用malloc將新值分配給t )。 在接下來的調用中, t本身不會被修改,只會修改它所指向的內容。 例如,改變t->root指cahnge由指向的內容t ,但不t本身(地址它指向)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM