有关引用的汇编层面探索
基础知识:其实所谓的指针和普通变量无本质区别,就看编译器怎么去解读他,如果是值就直接取出来用;如果是指针,就先把内存中的值读出来,作为地址再去读这个地址中的值,编译器会建立一张表:对应名字和地址。
注:本例在VS2008中观看C++代码的汇编解释,m对应的内存为0012FF60;p的内存地址为0012FF3C;m_a的内存地址为0012FF48
1定义:
普通变量的定义:
int m=5;
004114CE mov dword ptr [m],5 //因为它是int型,会占4个字节,[m]就相当于[0012FF60],所以意思就是内存中0012FF60开始的这四个字节的值就是5。
指针:
int* const p=&m;
004114EB lea eax,[m] //意思是把m的值,也就是0012FF60作为地址传给eax寄存器。
004114EE mov dword ptr [p],eax //这句话的意思把m_a对应的内存0012FF3C开始的四个字节的值设为0012FF60
再来看看引用:
int& m_a=m;
004114DC lea eax,[m] //意思是把m的值,也就是0012FF60作为地址传给eax寄存器。
004114DF mov dword ptr [m_a],eax //这句话的意思把m_a对应的内存 0012FF48 开始的四个字节的值设为0012FF60
可以看出:和指针一摸一样。其实引用和指针一样也要占内存。
2操作
m_a=4;
004114E2 mov eax,dword ptr [m_a] //把m_a对应的内存0012FF48开始的四个字节的值(为内存0012FF60)赋给eax寄存器。
004114E5 mov dword ptr [eax],4 //把4赋值给eax对应的内存0012FF60开始的四个字节的值。
对指针一样:
*p=3;
004114FA mov eax,dword ptr [p]
004114FD mov dword ptr [eax],3
相比对变量操作多了一个先取出指针的值,作为地址再进行操作的步骤。
3指针和引用作为形参
如下所示:
void swap(int& a,int& b)
{
004113B0 push ebp
004113B1 mov ebp,esp
004113B3 sub esp,0CCh
004113B9 push ebx
004113BA push esi
004113BB push edi
004113BC lea edi,[ebp-0CCh]
004113C2 mov ecx,33h
004113C7 mov eax,0CCCCCCCCh
004113CC rep stos dword ptr es:[edi]
int c=a;
004113CE mov eax,dword ptr [a]
004113D1 mov ecx,dword ptr [eax]
004113D3 mov dword ptr [c],ecx
a=b;
004113D6 mov eax,dword ptr [a]
004113D9 mov ecx,dword ptr [b]
004113DC mov edx,dword ptr [ecx]
004113DE mov dword ptr [eax],edx
b=c;
004113E0 mov eax,dword ptr [b]
004113E3 mov ecx,dword ptr [c]
004113E6 mov dword ptr [eax],ecx
}
void swap1(int* a,int* b)
{
00411400 push ebp
00411401 mov ebp,esp
00411403 sub esp,0CCh
00411409 push ebx
0041140A push esi
0041140B push edi
0041140C lea edi,[ebp-0CCh]
00411412 mov ecx,33h
00411417 mov eax,0CCCCCCCCh
0041141C rep stos dword ptr es:[edi]
int c=*a;
0041141E mov eax,dword ptr [a]
00411421 mov ecx,dword ptr [eax]
00411423 mov dword ptr [c],ecx
*a=*b;
00411426 mov eax,dword ptr [a]
00411429 mov ecx,dword ptr [b]
0041142C mov edx,dword ptr [ecx]
0041142E mov dword ptr [eax],edx
*b=c;
00411430 mov eax,dword ptr [b]
00411433 mov ecx,dword ptr [c]
00411436 mov dword ptr [eax],ecx
}
void swap2(int a,int b)
{
00411460 push ebp
00411461 mov ebp,esp
00411463 sub esp,0CCh
00411469 push ebx
0041146A push esi
0041146B push edi
0041146C lea edi,[ebp-0CCh]
00411472 mov ecx,33h
00411477 mov eax,0CCCCCCCCh
0041147C rep stos dword ptr es:[edi]
int c=a;
0041147E mov eax,dword ptr [a]
00411481 mov dword ptr [c],eax
a=b;
00411484 mov eax,dword ptr [b]
00411487 mov dword ptr [a],eax
b=c;
0041148A mov eax,dword ptr [c]
0041148D mov dword ptr [b],eax
}
4总结:
1.说明指针和引用在汇编层面就是一个东西,都是储存了变量的地址。
2.在高级语言层面不同,仅仅是限制的不同,一旦你申明了一个变量是指针或者引用之后,编译器解释他们和普通变量的时候就不一样了。
比如上面的:
int m=5;
int& m_a=m;
int* const p=&m;
3.有了以上定义之后,你写*p编译器一看,啊,这个我认识,这是指针,需要先取地址,再操作这个地址对应的值;而你如果写m_a,编译器一看,啊,
这个我也认识,这是引用,虽然没打*我也要先取地址再操作这个地址对应的值。
4.平时都说m_a只是一个m的别名,他们其实是一个东西,如果真是这样的话,对m_a和m操作应该是一样的,对吗?
其实不然,从上面的汇编代码可以看出
你用引用的时候,编译器需要多执行一条代码才能访问到m。所以用变量本身比用引用效率高!
水平有限,文中不妥之处,请高手纠正!
版权所有,转载请注明出处:http://blog.csdn.net/WXWTJ