没错,没有任何差别,定义一个引用和一个指针的汇编代码完全一致!
三、const哪里去了
相信从上面的分析时,你可能已经相信了,引用实际上就是一个指针。那么为什么说引用是一个常量指针呢,在目标代码里有什么体现呢?
这个问题其实要从C++底层机制谈起,C++为我们提供的各种存取控制仅仅是在编译阶段给我们的限制,也就是说编译器确保了你在完成任务之前的正确行为,如果你的行为不正确,那么编译器就是给你在编译时提示错误。所谓的const和private等在实际的目标代码里根本不存在,所以在程序运行期间只要你愿意,你可以通过内存工具修改它的任何一个变量的值。
这也就解释了为什么上面的两段代码中引用和指针的汇编代码完全一致。
C++设计引用,并用常量指针来从编译器的角度实现它,目标是为了提供比指针更高的安全性,因为常量指针一旦与变量地址绑定将不能更改,这样降低了指针的危险系数,它提供了一种一对一的指针。
但是你觉得使用引用就安全了吗?它同样会有与使用指针一样的问题
1 int *var = new int(42); 2 int &ref = *var; 3 delete var; 4 ref = 42; 5 return 0;
上面这段代码就很不安全,因为ref引用的内存区域不合法。
为了进一步验证引用与指针在本质上的相同,我们看当引用作为函数参数传递时,编译器的行为:
1 void Swap(int& v1, int& v2); 2 void Swap(int* v1, int* v2); 3 4 int var1 = 1; 5 00A64AF8 mov dword ptr [var1],1 6 int var2 = 2; 7 00A64AFF mov dword ptr [var2],2 8 Swap(var1,var2); 9 00A64B06 lea eax,[var2] 10 00A64B09 push eax 11 00A64B0A lea ecx,[var1] 12 00A64B0D push ecx 13 00A64B0E call Swap (0A6141Fh) 14 00A64B13 add esp,8 15 Swap(&var1, &var2); 16 00A64B16 lea eax,[var2] 17 00A64B19