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

标签 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) 

最佳答案

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

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

关于c++ - 通过引用传递表达式与通过引用传递变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57221599/

相关文章:

c - 为什么这是无效的 C 代码?

C++ 字符数组 : error while copying data

c++ - 避免空指针

c++ - 无法从 'void' 转换为 'Token' (C++)

c++ - 如何将使用 CUDA 的 C++ 程序转换为 MEX

c++ - 你能通过取消引用指针来返回一个整数吗?

c++ - 当引用变量为 'dies' 时,引用变量会发生什么?

c++ - 如何使用 boost::date_time 从 time_t 获取本地日期时间?

c++ - INC 操作码编译到错误的地址

c - 奇怪的 Char* 截断