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

C++ 通过引用传递表达式与通过引用传递变量,c++,pointers,lvalue,C++,Pointers,Lvalue,在下面显示的代码中,func(a3)输入if条件并生成输出“hi”。但是,当函数的参数是表达式时,会观察到不同的行为 例如,func(a1->right)不输入if条件 #包括 使用名称空间std; 类节点{ 公众: int数据; 节点*左、*右、*父节点; 公众: 节点(int数据):数据(data){ 左=空PTR; 右=空PTR; 父项=nullptr; } ~Node(){} }; void func(节点*&节点){ 节点*p=节点->父节点; p->右=节点->左; 如果(节点->左

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

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

#包括
使用名称空间std;
类节点{
公众:
int数据;
节点*左、*右、*父节点;
公众:
节点(int数据):数据(data){
左=空PTR;
右=空PTR;
父项=nullptr;
}
~Node(){}
};
void func(节点*&节点){
节点*p=节点->父节点;
p->右=节点->左;
如果(节点->左){
cout left->parent=p;
}
节点->父节点=p->父节点;
}
int main(){
节点*a1=新节点(10);
节点*a2=新节点(20);
节点*a3=新节点(30);
节点*a4=新节点(40);
节点*a5=新节点(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
*/
/*案例1:打印hi*/
func(a3);
/*案例2:不打印hi*/
//func(a1->右);
/*案例3:打印hi*/
//节点*ptr=a1->右侧;
//func(ptr);
}
我有两个问题:

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

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

  • 编辑: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->右=节点->左
    实际上将
    a1->right
    设置到不同的节点

    在案例3中,您将引用传递给一个局部变量
    ptr
    ,该变量不会被更改,因为它是一个副本

    如果您添加:

    cout
    将表达式引用传递给func而不是变量引用时出现不同行为的原因

    原因是程序中复杂的逻辑。在这种特殊情况下,当您传递
    a3
    a1->right
    时,任一指针都指向同一个对象,但
    func()
    本身会修改
    a1->right
    ,因此,当引用传递
    a3
    时,更改不会影响
    节点
    ,但当传递
    a1->right
    时会影响。亨斯发现了差异

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


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

    作为旁白,不要包含
    位/stdc++.h
    ,因为它带来了所有东西,而您只想带来一些东西。注意@AndyG。我现在看到了问题。您应该使用调试器逐步完成此操作,并观察树的外观。我要说的是,没有理由在
    func
    中通过引用接收您的ptr。您可以修改传入的内容。因此,它可能与进行不同函数调用的顺序有关。通过引用传递指针的原因是什么?除了使代码过于复杂之外。那么为什么node->left变为null(请参考新包含的gdb输出)。
    node->left
    变为null,因为
    node
    现在指向另一个没有left-chidl的节点。a1->右侧是a3,所以节点->左侧是a3->左侧,此时为a5。a5->left为空。(我希望我没有弄错)