关于通过引用传递指针的说明

时间:2018-05-23 00:04:32

标签: c++ pointers linked-list

这有点傻,但我无法解释为什么会这样。作为练习,我想反转一个单链表,我通过定义方法来做到这一点:

class solution {
    void reverseLinkedList(Node*& head) {
      Node* curr = head;
      Node* prev = NULL;
      while (curr != NULL) {
        Node* _next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = _next;
      }
      head = prev;
}

在我的主要功能中,我拨打电话

solution s;
s.reverseLinkedList(head);

Node* iterator = head;
while (iterator != NULL) {
    std::cout<<iterator->data<<std::endl;
    iterator = iterator->next;
}

我之前定义了指向某个链表的头指针。 while循环用于打印我的链表,该功能可以正常工作。这仅在我通过引用传递头节点后才起作用;我最初尝试传递Node * head而不是Node *&amp;在开头,它只打印我的链表的第一个元素(并没有反转它)。例如,如果我没有通过引用传递列表1-&gt; 2-&gt; 3,我会打印出1。

我认为传指针就够了吗?为什么我没有通过引用&gt;

传递这种奇怪的行为

4 个答案:

答案 0 :(得分:2)

C ++中的局部变量(存储在堆栈中)具有块范围,即,在执行定义它们的块之后,它们会超出范围。

当您传入指向该函数的指针时,会创建指针的副本,并且该副本将被传递。执行该函数后,函数工作区中的变量超出范围。在函数中创建的任何非静态自动变量都将被销毁。

当您通过引用传入时,您不会传入变量的副本但传入实际变量,因此对变量所做的任何更改都会反映在传递给函数的实际变量中(通过引用)。

我想指出,指向下一个节点的指针存储在内存中,并且有一个存储位置的地址。因此,如果您不想通过引用传入,可以执行以下操作:

  1. 使用指向指针的指针,指针指向存储下一个节点的指针变量(地址)的内存位置
  2. 将此传递给函数(不是通过引用)
  3. 取消引用指针并存储您想要指向的新地址。
  4. 我知道这有点令人困惑,但请看一下将一个节点添加到链表中的这一小段代码。

    void addNode(Node** head, int newData)
    {
        Node* newNode = new Node;
        newNode->data = newData; // Can also be done using (*newNode).data
        newNode->next = *head;
        *head = newNode;
    }
    

答案 1 :(得分:1)

  

我以为传指针就足够了?

<div class="input-group-prepend w-50"> /* grows to 50% of parent*/
  <label class="input-group-text w-100" id="licenseEmaillabel"> /* grows to 100% of parent */

按值传递void reverseLinkedList(Node* head) // pass pointer by value // head is a copy here 会创建要在函数内使用的副本
对函数内部指针所做的任何更改仅反映在函数范围内。
由于这些更改仅反映在指针的副本中,而原始指针中的不是

一旦pointer(副本)超出范围,这些更改将被丢弃&#34;由于生命的终结。

因此,您需要一个参考。

pointer

答案 2 :(得分:0)

当您定期传递指针(IE按值)时,它会创建指针的副本。对此指针所做的任何更改都不会影响原始指针。

通过引用传递指针是发送对该指针的引用(非常类似于将指针传递给指针),因此对该指针所做的任何更改都会影响其“原始”状态。

例如:

//WRONG does not modify the original pointer, causes memory-leak.
void init(Object* ptr, int sz) {
    ptr = new T[sz]; 
}

VS

 //Correct original pointer is a set to a new block of memory
void init(Object*& ptr, int sz) {
    ptr = new T[sz]; 
}

答案 3 :(得分:0)

void reverseLinkedList(Node* head)

指针按值传递。

这听起来很傻,这是一个怪异的指针,对吧?通过引用传递的定义的种类。好吧,指向Node通过引用传递。 指针本身head只是另一个变量,恰好包含其他变量的地址,并且它的不是通过引用传递。

因此head包含用于调用Node的{​​{1}}指针的副本,并且与按值传递的所有参数一样,对副本进行任何修改,指向reverseLinkedList在其他地方,没有在调用函数中表示。