2010-10-07 81 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并做一个任务。

相关问题