引用本质究竟是什么?或者说引用在计算机底层是怎么实现的?
我们来看下面一段C++代码:
(1) int x = 5;
(2) int &y = x;
(3) y = 8;
在VS2013下反汇编得到下面汇编代码:
//对应(1)
mov dword ptr [x], 5 // 将常量5送入变量x中
//对应(2)
lea eax, [x] // 取x的地址并送入eax寄存器中
mov dword ptr [y], eax // 将eax寄存器中的内容送入变量y中
//对应(3)
mov eax, dword ptr [y] // 将变量y中的内容送入eax寄存器中
mov dword ptr [eax], 8 // 将常量8送入以eax为地址的内存单元中
从汇编代码中可以看出,y的类型为dword,占据4个字节。因此,y实际上就是一个变量,它存放被引用变量的地址。一般来说,地址是由指针变量保存的,那么引用变量和指针变量有什么区别呢?
我们接着看下面一段代码:
(a) int x = 5;
(b) int * const y = &x ;
(c) *y = 8;
在VS2013下反汇编得到下面汇编代码:
//对应(a)
mov dword ptr [x], 5
//对应(b)
lea eax, [x]
mov dword ptr [y], eax
//对应(c)
mov eax, dword ptr [y]
mov dword ptr [eax], 8
我们惊奇的发现所得的汇编代码和第一段所对应的汇编代码完全一样。因此,引用变量在功能上相当于指针常量,即一旦指向某个单元就不能再改变。在底层,引用变量也是按照指针常量的方式来实现的。
在高级语言层面上,引用变量和指针常量的关系如下:
(1) 在内存中都占据4个字节的空间,存放的都是被引用对象的地址,都必须在定义的时候初始化。
(2) 指针常量本身允许寻址(以x为例),即&x是指针常量所在内存单元的地址,被引用对象用*x表示;引用变量不允许寻址(以y为例),&y指的是被引用对象的地址(即y本身),并不是y所在内存单元的地址(y的地址有编译器管理,程序员无法访问),被引用对象直接用y表示。