引用与指针在底层实现研究

来源:互联网 发布:电台 知乎 编辑:程序博客网 时间:2024/06/05 23:48

    这个题目最初是学弟问我的.很认真的和学弟一起讨论了这个问题,最终得到这一篇文章(ps但是当时还真是吓了一跳,发现学弟的水平真是日进千里,已经开始考虑底层(汇编相关的东西).)

   关于指针与引用的区别网上有很多好的文章,比如这一篇:


http://blog.csdn.net/dujiangyan101/article/details/2844138  

    从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。
而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。这二者起码在表意上是不同.

    然而在VS环境下,进行反汇编,却会发现二者的实现是有共同之处.

源代码:


#include<stdio.h>int main(){int m_int = 0;int* m_ptr = &m_int;int& m_ref = m_int;}

生成的汇编代码:

#include<stdio.h>


int main()
{
012A13B0  push        ebp  
012A13B1  mov         ebp,esp  
012A13B3  sub         esp,0E8h  
012A13B9  push        ebx  
012A13BA  push        esi  
012A13BB  push        edi  
012A13BC  lea         edi,[ebp-0E8h]  
012A13C2  mov         ecx,3Ah  
012A13C7  mov         eax,0CCCCCCCCh  
012A13CC  rep stos    dword ptr es:[edi]  
012A13CE  mov         eax,dword ptr ds:[012A8000h]  
012A13D3  xor         eax,ebp  
012A13D5  mov         dword ptr [ebp-4],eax  
int m_int = 0;
012A13D8  mov         dword ptr [m_int],0  
int* m_ptr = &m_int;
012A13DF  lea         eax,[m_int]  
012A13E2  mov         dword ptr [m_ptr],eax  
int& m_ref = m_int;
012A13E5  lea         eax,[m_int]  
012A13E8  mov         dword ptr [m_ref],eax  
}


从上面的代码可以看出无论引用还是指针在定义初始化阶段都采用一样的汇编代码来实现的:

 lea         eax,[m_int]  
 mov         dword ptr [m_ref],eax  

代码简单易懂,就是贱m_int的(偏移)地址存放到对应的指针/引用的内存中,

从上面我们可以的出一个结论,引用于指针二者在实现上是类似的.

查询了相关的资料,我得出一个结论那就是引用是一个常量指针.然而这一切都只是编译器这么做,因为在C99的文档里是没有要求别名要这么实现,编译器这么做是可行的,(关于编译器与文档之间也有很多有趣的话题,等以后有机会再接着写一写文章),但是编译器屏蔽了引用和指针的差别。

  以上的内容都是在VC/VS编译环境中,实现的.我在网上还找到了在gcc上讨论这二者的文章

http://my.oschina.net/fergus/blog/123490

   但是我们依旧要明确,引用就是引用,虽然在实现上是采用指针的技术,但是由于编译器的作用,引用与指针有着巨大的不同,这一点还是要明确的,

最后,感谢亲爱的逆袭同学(可惜他不会看这篇文章,嘿嘿)







0 0