从底层汇编理解 c++ 引用实现机制

   引用类型到底是什么?它和指针有什么关系?它本身占用内存空间吗? 带着这些疑问,我们来进行分析。 先看代码:

#include <stdio.h>
#include <iostream>

using namespace std;


void main()
{
   int x = 1;
   int &b = x;
 } 

  通过汇编查看代码如下:

9:       int x = 1;
00401048   mov         dword ptr [ebp-4],1
10:      int &b = x;
0040104F   lea         eax,[ebp-4]
00401052   mov         dword ptr [ebp-8],eax

  可以知道x的地址为ebp-4,b的地址为ebp-8,因为栈内的变量内存是从高往低进行分配的。所以b的地址比x的低。
  lea eax,[ebp-4]  这条语句将x的地址ebp-4放入eax寄存器

  mov dword ptr [ebp-8],eax 这条语句将eax的值放入b的地址ebp-8中

  上面两条汇编的作用即:将x的地址存入变量b中,这不和将某个变量的地址存入指针变量是一样的吗?

   所以从汇编层次来看,的确引用是通过指针来实现的

   下面我们通过程序来验证,我们知道,在程序一层我们只要直接涉及到引用变量的操作,我们操作的总是被引用变量,即编译器帮我们做了些手脚,总是在引用前面加上*。所以我们要读取真正的“引用变量的值”,必须采取一定的策略,好吧,我们就按照变量在栈中分布的特点来绕过编译器的这个特点。

#include <stdio.h>
#include <iostream>

using namespace std;

void main()
{
   int x = 1;
   int y = 2;
   int &b = x;
   printf("&x=%x,&y=%x,&b=%x,b=%x\n",&x,&y,&y-1,*(&y-1));
 } 

  输出结果为:&x=12ff7c,&y=12ff78,&b=12ff74,b=12ff7c
  Press any key to continue

void main()
{
   int x = 1;
   int &b = x;
   printf("&x=%x,&b=%x\n",&x,&b);
 } 

  输出结果为::&x=12ff7c,&b=12ff7c.

  b的地址我们没法通过&b获得,因为编译器会将&b解释为:&(*b) =&x ,所以&b将得到&x。也验证了对所有的b的操作,和对x的操作等同。

  但是我们可以间接通过&y-1来得到b的地址,从而得到b的值:*(&y-1)  从结果可以知道,b的值即x的地址,从而可以知道,从地层实现来看,引用变量的确存放的是被引用对象的地址,只不过,对于高级程序员来说是透明的,编译器屏蔽了引用和指针的差别。

  下面是程序的变量在内存栈中的分布,引用变量一样也占用内存空间,而且应该是4个字节的空间。

   虽然从底层来说,引用的实质是指针,但是从高层语言级别来看,我们不能说引用就是指针,他们是两个完全不同的概念。有人说引用是受限的指针,这种说法我不赞同,因为从语言级别上,指针和引用没有关系,引用就是另一个变量的别名。对引用的任何操作等价于对被引用变量的操作。从语言级别上,我们就不要去考虑它的底层实现机制啦,因为这些对你是透明的。所以在面试的时候,如果面试的人问到这个问题,可以先从语言级别上谈谈引用,深入的话就从底层的实现机制进行分析。而不能什么条件没有就说:引用就是指针,没有差别,......之类的回答

 

 以下内容摘自网上,觉得挺好的,借用过来

  什么是引用? 

  对象的别名(另一个名称)。

  引用经常用于“按引用传递(pass-by-reference)”:

 void swap(int& i, int& j)
 {
   int tmp = i;
   i = j;
   j = tmp;
 }
 
 int main()
 {
   int x, y;
   
// ...
   swap(x,y);
 }

  此处的 ij 分别是main中的 xy。换句话说,i 就是x —— 并非指向 x 的指针,也不是x 的拷贝,而是 x 本身。对 i 的任何改变同样会影响x,反之亦然。

  OK,这就是作为一个程序员所认知的引用。现在,给你一个不同的角度,这可能会让你更糊涂,那就是引用是如何实现的。典型的情况下,对象 x 的引用ix 的机器地址。但是,当程序员写 i++ 时,编译器产生增加 x 的代码。更详细的来说,编译器用来寻找x 的地址位并没有被改变。C 程序员将此认为好像是 C 风格的按指针传递,只是句法不同 (1) 将 & 从调用者移到了被调用者处,(2)消除了*s。换句话说,C 程序员会将i 看作为宏(*p),而 p 就是指向 x 的指针(例如,编译器自动地将潜在的指针解除引用;i++被改变为(*p)++i = 7 被自动地转变成*p = 7)。

  很重要:请不要将引用看作为指向一个对象的奇异指针,即使引用经常是用汇编语言下的地址来实现的。引用就是对象。不是指向对象的指针,也不是对象的拷贝,就是对象。

 

 

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值