通常我们会说,引用和指针的区别在于——引用只是一个别名。但事实真的如此吗?

下面通过几段反汇编代码来看看编译器实际是如何处理引用的。

函数参数中的引用

先看一段反汇编片段:

.
明显 参数占了4字节的栈空间
.

可以看到,引用类型的参数在栈上实实在在占用了 4 个字节的空间,和一个指针参数并无区别。

局部变量中的引用

再看下面这段代码对应的反汇编:

int &s = x;
003A493D  lea         eax,[x]
003A4940  mov         dword ptr [s],eax

明显s是一个变量

这里更加清楚:s 并不是 x 的一个纯粹"别名",而是一个真实存在的变量——编译器先用 lea 取出 x 的地址,再把这个地址 movs 对应的内存单元中。换句话说,s 里存放的是 x 的地址。

引用的本质

基于以上观察,基本可以推断:引用在实现层面就是一个类似 const 指针的东西。下面这两行代码在机器层面可以认为是等价的:

int x = 5;

int &s = x;
const int *s2 = &x; /*等价*/

所谓"引用是别名"更多是语言层面提供给程序员的抽象;到了编译器和机器码这一层,引用和常量指针并没有本质差别。