欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 从汇编的角度揭秘C++引用,豁然开朗

从汇编的角度揭秘C++引用,豁然开朗

2025/6/13 19:09:13 来源:https://blog.csdn.net/zhongleyun/article/details/148409299  浏览:    关键词:从汇编的角度揭秘C++引用,豁然开朗

C++中的引用是指已有对象的别名,可以通过该别名访问并修改被引用的对象。那么其背后的原理是什么呢?引用是否会带来额外的开销呢?我们从一段代码入手,来分析一下引用的本质。

#include <stdio.h>
int main()
{int a = 10;int &b = a;b = 11;return 0;
} 

如上所示:定义了一个int型变量a,以及一个int型的引用b,并指向a。最后将b的值修改为11。

我们来看一下它对应的汇编代码:

      1  pushq   %rbp2  movq    %rsp, %rbp        //rbp = rsp 3  movl    $10, -12(%rbp)   //*(rbp-12) = 104  leaq    -12(%rbp), %rax  //rax = rbp - 125  movq    %rax, -8(%rbp)  //*(rbp - 8) = rax6  movq    -8(%rbp), %rax  //rax = *(rbp - 0x8)7  movl    $11, (%rax)     //*rax = 11;8  movl    $0, %eax9  popq    %rbp10  ret

我们来逐行分析:

先来介绍两个寄存器:

rsp:栈顶指针寄存器,rbp:栈基址指针寄存器。前两行push %rbp,以及move %rsp, %rbp。是保存函数调用之前的上下文信息,以及让rbp等于rsp。即此时main函数的栈空间是空的,这两条指令相当于main函数的准备工作。此时main函数的调用栈如下所示:

接下来:movl    $10, -12(%rbp),是将一个立即数写入rbp-12这个地址中,写入栈空间如下所示:

通过对比源代码,发现这条指令对应的是这行:int a = 10。接下来leaq    -12(%rbp), %rax,是将rbp-12的地址加载进rax, 即rax = rbp-12。也就是变量a的地址。接下来movq    %rax, -8(%rbp),即将rax(rax为rbp-12)写入rbp-8这个地址。执行完这条之后,栈上的分布如下:

即将rbp-12存入rbp-8这个地址中。rbp-12即是a的地址。这里其实就是引用的一个实现。接下来:movq    -8(%rbp), %rax,即将rbp-8地址里的内容(即rbp-12)赋值给rax, 即rax = rbp-12。接下来:movl    $11, (%rax) ,即将立即数11赋值给rax所指地址。rax为rbp-12, 那么rbp-12这个地址中的内容将被赋值为11。rbp-12即a的地址,那么执行完这条指令之后,a的值将被更新为11。栈上的分布如下:

对应源码即是b=11。此时,已经完成了通过引用将被引用对像值更新的过程。由此,我们可以看出,C++中引用实现的本质就是指针,即通过存储被引用对象的地址来实现。但是它比指针更加安全,可以认为是一个指针的语法糖。

此文对应的B栈视频如下:

用汇编揭秘C++引用的本质,豁然开朗_哔哩哔哩_bilibili

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词