通过引用传递表达式vs通过引用传递变量

时间:2019-07-26 13:58:56

标签: c++ pointers lvalue

在下面显示的代码中,func(a3)输入if条件并产生输出“ hi”。但是,当函数的参数为​​表达式时,会观察到不同的行为。

例如,func(a1->right)不输入if条件。

#include <iostream>
using namespace std;
class Node {
   public:
    int data;
    Node *left, *right, *parent;

   public:
    Node(int data) : data(data) {
        left = nullptr;
        right = nullptr;
        parent = nullptr;
    }
    ~Node() {}
};
void func(Node*& node) {
    Node* p = node->parent;
    p->right = node->left;
    if (node->left) {
        cout << "hi\n";
        node->left->parent = p;
    }
    node->parent = p->parent;
}
int main() {
    Node* a1 = new Node(10);
    Node* a2 = new Node(20);
    Node* a3 = new Node(30);
    Node* a4 = new Node(40);
    Node* a5 = new Node(50);
    a1->left = a2; a2->parent = a1;
    a1->right = a3; a3->parent = a1;
    a3->left = a4; a4->parent = a3;
    a3->right = a5; a5->parent = a3;
    /*
         a1
       /   \
     a2     a3
           /  \
           a4   a5
     */

    /* Case 1: prints hi */
    func(a3);

    /* Case 2: doesn't print hi */
    // func(a1->right);


    /* Case 3: prints hi */
    // Node* ptr = a1->right;
    // func(ptr);
}

我有两个问题:

  1. 表达式引用传递给func而不是变量引用

  2. 表达式的引用传递给函数的惯用方式是什么。

编辑:gdb输出

(gdb) b 17
Breakpoint 1 at 0x555555554856: file pointer_ref.cpp, line 17.
(gdb) r
Starting program: /home/a.out 

Breakpoint 1, func (node=@0x555555767e80: 0x555555767ed0) at pointer_ref.cpp:18
18      Node* p = node->parent;
(gdb) p node->data 
$1 = 30 // a3
(gdb) n
19      p->right = node->left;
(gdb) p p->data
$2 = 10 // a1
(gdb) n
20      if (node->left) {
(gdb) p p->right->data
$3 = 40 // a4
**(gdb) p node->left->data
Cannot access memory at address 0x0**
// ^^^ This seems to be the problem location
// After changing p->right to node->left,
// somehow, node->left becomes null 
(gdb) p node->left
$4 = (Node *) 0x0
(gdb) 

2 个答案:

答案 0 :(得分:1)

您已传递对a1->right的引用。因此,您对该字段所做的任何更改都可以在该函数中看到。 p->right = node->left;实际上将a1->right设置为另一个节点。

在情况3中,您将引用传递给局部变量ptr,该变量不变,因为它是一个副本。

如果添加:

    cout << "node was " << node << std::endl;
    p->right = node->left;
    cout << "node is " << node << std::endl;

您将看到您的节点发生了变化。

答案 1 :(得分:0)

  

将表达式的引用传递给func而不是引用变量时会导致不同的行为吗?

原因是程序中令人费解的逻辑。在这种特殊情况下,当您传递a3a1->right时,任何一个指针都指向同一对象,但是func()本身会修改a1->right,因此当传递对a3的引用时该更改不会影响node,但会在a1->right通过时对其产生影响。细细区别。

  

将表达式的引用传递给函数的惯用方式是什么。

以您的方式传递引用没有问题,问题是数据关系过于复杂。例如,在您的情况下,没有理由按引用传递此指针。

相关问题