牛客第一菜狗:关于引用的问题看来有所争议,严谨起见,我还是实验了一下,C++代码如下: int main(){
int a = 1;
scanf_s("%d", &a);
int &ya = a;
printf("%d %d\n", a, ya+1);
system("pause");
return 0;
} VS2015,DEBUG模式下生成了如下的汇编代码: int a = 1;
mov dword ptr [a],1
scanf_s("%d", &a);
lea eax,[a]
push eax
push offset string "%d" (01E6B30h)
call _scanf_s (01E10F5h)
scanf_s("%d", &a);
add esp,8
int &ya = a;
lea eax,[a]
mov dword ptr [ya],eax
printf("%d %d\n", a, ya+1);
mov eax,dword ptr [ya]
mov ecx,dword ptr [eax]
add ecx,1
push ecx
mov edx,dword ptr [a]
push edx
push offset string "%d %d\n" (01E6B34h)
call _printf (01E132Ah)
add esp,0Ch
很明显看到, int &ya = a; 这一句下面的反汇编,意思是“把a的地址装进寄存器eax,再把eax寄存器的值放到ya所在的地址段”。 很明显说明了,ya有自己独立的地址空间,在试图打印ya+1的值的时候: mov eax,dword ptr [ya]
mov ecx,dword ptr [eax]
这两行的意思是取ya地址段中的值(也就是&a,即a变量的地址)进寄存器eax,再将以“eax中的值作为地址”取四字节数字进ecx,两步合计相当于*(&a)。 另外对于RELEASE模式的代码,显然编译器聪明多了: printf("%d %d\n", a, ya+1);
mov ecx,dword ptr [a]
lea eax,[ecx+1]
push eax
push ecx
push offset string "%d %d\n" (03B210Ch)
这里就很接近原文说的“引用是别名”之类的概念了。 当然这种级别的优化下,变量很可能一直生活在寄存器中,简单的函数调用也很容易被自动内联展开。此时再去讨论什么地址的问题有点本末倒置,因为连原始变量绝大多数时间都不在内存里了。
0 点赞 评论 收藏
分享
创作者周榜
更多
关注他的用户也关注了: