美文网首页
C++中的引用推导

C++中的引用推导

作者: 01_Jack | 来源:发表于2019-11-12 21:21 被阅读0次

    导读

    • 为什么说引用是别名
    • 为什么引用作为形参可以修改实参的值
    • 为什么引用初始化后无法指向其他对象
    • 引用与指针对应的汇编代码
    • 对引用的理解

    为什么说引用是别名

    int main() {
        int a = 10;
        int &b = a;
        b = 20;
        return 0;
    }
    
    1-1

    从地址的角度来说,a与b两者的内存地址相同,都存储着0x14这个数值,所以b可以理解为a的别名。既然引用是别名,显然需要通过某个变量初始化,因此引用必须在定义的时候直接通过某个变量初始化。

    为什么引用作为形参可以修改实参的值

    void test(int &x) {
        x = 99;
    }
    
    int main() {
        int a = 10;
        test(a);
        return 0;
    }
    
    2-1 2-2

    在调用函数前,将a的地址存入rdi中,此时可以通过rdi存储的地址值来对变量a进行读写操作。

    2-3

    进入函数后,向rdi存储的内存地址中写入0x63数据,即十进制的99。由于rdi中存储的是变量a的内存地址,所以此时a的值等于99。

    为什么引用初始化后无法指向其他对象

    例子中的注释对应着汇编代码:

    int main() {
    //    movl   $0xa, -0x8(%rbp)
        int a = 10;
        
    //    leaq   -0x8(%rbp), %rcx
    //    movq   %rcx, -0x10(%rbp)
    //    movq   -0x10(%rbp), %rcx
        int &x = a;
        
    //    movl   $0x14, (%rcx)
        x = 20;
        
    //    movl   $0x63, -0x14(%rbp)
        int b = 99;
    
        return 0;
    }
    

    可以看到,在对引用赋值时,转成汇编对应的是通过寄存器赋值,中间通过movq %rcx, -0x10(%rbp)转存了一下a的内存地址。那么,是否可以通过-0x10(%rbp)这个内存地址来修改x的指向?

    3-1

    可见,当我们向-0x10(%rbp)内存地址中写入变量b的内存地址时,引用x的值变成了变量b的值99。虽然可以通过lldb修改引用的指向,但在C++层面很难得知引用的内存地址(即使通过代码中变量存储地址推导出引用地址,同样需要直接操作内存地址,因为没有一个变量名代表这个内存地址)。

    当对引用使用&符号时,得到的是变量a的地址,而非引用的地址(请参考为什么说引用是别名这一小节)。

    是否可以通过直接修改&引用的值,来达到改变引用指向?

    3-2

    很遗憾,&x无法赋值,因为&x等于变量a的地址,而a的地址是个常量,常量不能是左值。

    引用与指针对应的汇编代码

    int main() {
    //    movl   $0xa, -0x8(%rbp)
        int a = 10;
        
    //    leaq   -0x8(%rbp), %rcx
        
    //    movq   %rcx, -0x10(%rbp)
        int &x = a;
        
    //    movq   %rcx, -0x18(%rbp)
        int *p = &a;
        return 0;
    }
    

    从汇编代码来看,无法区分是在操作引用还是在操作指针,两者的区别仅在于可以通过&p获取指针的地址,从而改变指针变量p的指向,但是无法通过&x获取引用的地址(获取到的是a的地址)。

    对引用的理解

    文章开头已经说过,可以把引用理解为变量的别名。但是通过为什么引用初始化后无法指向其他对象这一小节可以看到,引用其实也是需要开辟内存的,只是内存地址没有对应的变量名,在这个内存地址中存储着引用的变量的内存地址,可以把这块因为引用而开辟的匿名内存地址理解为二级指针。
    此处可以类比指针,指针存储着某个变量的地址,但是同样有一块空间存储着指针,而这块存储着指针的内存空间就是&指针,即指针的地址,引用其实就是个匿名指针。


    Have fun!

    相关文章

      网友评论

          本文标题:C++中的引用推导

          本文链接:https://www.haomeiwen.com/subject/whzfictx.html