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

Passing an expression by reference vs Passing variable by reference

本文关键字:引用 变量 表达式      更新时间:2023-10-16

在下面显示的代码中,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 << "hin";
        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. 什么是
  3. 表达式引用传递给函数的惯用方式。

编辑: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) 

您已将引用传递给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;

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

当表达式的引用传递给 func 而不是变量的引用时,不同行为的原因是什么?

原因就是程序中复杂的逻辑。在这种特殊情况下,当您传递a3a1->right任一指针指向同一对象时,func()本身会修改a1->right因此,当引用传递a3时,更改不会影响node但当a1->right传递时,它会影响。亨斯与众不同。

什么是

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

没有以

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