美文网首页
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++中的引用推导

    导读 为什么说引用是别名 为什么引用作为形参可以修改实参的值 为什么引用初始化后无法指向其他对象 引用与指针对应的...

  • C++学习:Effective Modern C++条款

    条款1:理解模板类型推导 推导模版类型时,引用的值视为非引用,即忽略引用。 推导通用引用类型参数时,左值特殊处理。...

  • C++基础

    C++ 值传递、指针传递、引用传递详解C++中引用传递与指针传递区别 引用传递和指针传递的区别 引用的规则:(1)...

  • 模板类型推导与auto

    本文聊聊C++中的模板类型推导和auto。两者其实是一样的,前者推导T的类型,后者推导auto的类型。本文初创于公...

  • 指针和引用的区别

    参照lyd_253261362的专栏的文章详细介绍=====c++中的引用与指针的区别 c++中的引用与指针的区别...

  • Reference 引用

    c++之 引用&参数传递 引用是C++中的概念,初学者容易把引用和指针混淆一起。 一下程序中,n是m的一个引用(r...

  • java中的引用与c++中的指针的区别

    java中的引用与c++中的指针的区别 Java的引用和C++的指针都是指向一块内存地址的,通过引用或指针来完成对...

  • C++中的引用和指针

    C++ 引用与指针的比较 引用是 C++ 中的概念,初学者容易把引用和指针混淆一起。 以下程序中,n 是m的一个引...

  • C++中的引用

    在C++中新增加了引用的概念引用可以看做是一个已定义变量的别名引用的语法: Type& name = var; t...

  • C++中的引用

    下面的代码中,n是m的引用(reference),m是n的被引用物(referent) int m = 6; in...

网友评论

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

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