2010-10-07 78 views
0

這是一個noobie問題,但我不確定如何通過引用在C++中傳遞。我有以下的課程,它建立了一個節點和一些功能。在C++中通過引用傳遞一個對象

class Node 
{ 
    public: 
    Node *next; 
    int data; 
    Node(int dat) 
    { 
     next = NULL; 
     data = dat; 
    } 
    Node* getNext() 
    { return next; } 
    void setNext(Node *n) 
    { next = n;} 

    void reverse(Node *root) 
    { 
     Node *previous = NULL; 
     while(root != NULL) 
     { 
     Node *next = root->getNext(); 
     root->setNext(previous); 
     previous = root; 
     root = next; 
     } 
     root = previous; 
    } 
}; 

現在,我的小班的目的是創建一個單一的鏈接列表,並有能力扭轉它。如果我在返回結束時返回名爲'previous'的節點,它似乎工作正常。

但看看我的主要功能:

int main() 
{ 
    Node *root = new Node(1); 
    Node *num2 = new Node(2); 
    Node *num3 = new Node(3); 
    Node *num4 = new Node(4); 

    root->setNext(num2); 
    num2->setNext(num3); 
    num3->setNext(num4); 
    root->printList(); 
    root->reverse(root); 
    root->printList(); 

    return 0; 
} 

的printList()被省略了空間的緣故,但它只是打印給出一個節點列表。問題是,當調用root-> reverse(root)時,root實際上並不會指向'previous'。

輸出會是這樣:

1 
2 
3 
4 
    // the value of previous from the reverse function is 4 
1 

我真的不明白輸出。任何人都在意解釋發生了什麼? (爲什麼不反轉列表,即使我做了像這樣的root = root-> reverse(root),其中反向返回前一個,它會)爲什麼現在root只指向它自己?我是新來的C++,並感謝您的幫助!

+0

應該提到的是,該程序正在泄漏內存,因爲C++的資源管理(即RAII)被繞過。 – Arafangion 2010-10-07 02:43:00

+0

我真的不知道那麼多關於C++的管理,關心告訴我它在哪裏泄漏內存,也許我該如何修復它?我知道我應該只是閱讀文檔,但像這樣的真實世界的例子可以幫助點燃火災:) – kodai 2010-10-07 02:46:27

+1

基本上,如果你調用new,你需要自己管理內存,這意味着調用delete。每個新的都必須有相應的刪除。不使用新的(即,只是在做'Foo foo'而不是'Foo * foo = new Foo()'),意味着你可以讓C++爲你管理這個資源,你不需要擔心刪除它。 (事實上​​,這樣做是錯誤的)。 – Arafangion 2010-10-07 03:04:29

回答

3

C++支持引用語義。因此,對於一個給定函數:

void foo(Bar& bar); 

按引用傳遞你這樣做:

int main() { 
    Bar whatsit; 

    foo(whatsit); 

    return 0; 
} 

這就是它!

void foo(Bar* bar); 

你會怎麼做:

int main() { 
    Bar whatisit; 

    foo(&whatsit); 

    return 0; 
} 

的區別主要是語義的問題:

這通常與傳遞指針,其中一個功能,如混淆 - 一個參考總是有效的。沒有理由檢查一個NULL指針。 - 指針可能爲NULL,因此應該檢查。

然而,如果程序員決定是邪惡和濫用引用語義,但是原則依然存在,那麼引用可能引用NULL指針。

+0

所以我想我明白你們對於通過價值傳遞指針的意思是什麼意思。我明白爲什麼反向(Node *&root)工作。我仍然不確定爲什麼類似:reverse(Node&root)會起作用。我試過了,它不會編譯。它是否與Root被聲明和調用的方式有關? (Node * root = new Node(1); root-> reverse(root)) – kodai 2010-10-07 01:01:49

+1

在那裏,root是指向Node的指針。這不是一個參考。 – Arafangion 2010-10-07 01:13:33

+1

將參數更改爲(節點和根)會使函數期望將節點傳遞給它。爲了這個工作,主要你要麼刪除指針,只需要創建Nodes(比如'Node root;'),調用像reverse(root)這樣的函數,或者保存指針並傳遞指針的實際節點指向,如反向(*根)。 – 2010-10-07 02:06:16

2

按引用傳遞一個指針,你可以聲明reverse爲:

void reverse(Node*& root) { 
    // ... 
} 
3

你是不是通過引用傳遞。您正在傳遞指針的副本。該副本仍然指向同一個節點,但它仍然只是本地範圍的副本。基本上它是另一個指向主節點的指針指向的節點(ha!)。在函數結束時,您的任務將分配previous到該指針副本,然後函數結束並且副本超出範圍。你的指針保持不變。

返回/分配指針的原因的工作原理是,已經設置爲你想要的這個副本被返回並分配給你的main指針。

您可以通過多種方式解決此問題。傳遞對你的指針的引用(醜陋的imo),使用引用,或者返回root並做一個任務。

相關問題