C++中的引用推导

导读

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

为什么说引用是别名

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!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 原文地址:https://niyaoyao.github.io/2016/07/29/Objective-C-Ru...
    mengjz阅读 3,529评论 0 0
  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 8,828评论 3 44
  • 指针 在了解什么是指针之前,我们需要先搞清楚数据在内存中是如何存储的,又是如何读取的。 如果在程序中定义一个变量,...
    Longshihua阅读 4,645评论 0 4
  • 几种语言的特性 汇编程序:将汇编语言源程序翻译成目标程序编译程序:将高级语言源程序翻译成目标程序解释程序:将高级语...
    囊萤映雪的萤阅读 8,060评论 1 5
  • 指针和引用形式上很好区别,但是他们似乎有相同的功能,都能够直接引用对象,对其进行直接的操作。但是什么时候使用指针?...
    代码人生ll阅读 3,184评论 0 0

友情链接更多精彩内容