3

我写了一个小程序:

#include <iostream>

using namespace std;

int raw(int &x) {
    cout<<x<<endl;
    cout<<&x<<endl;
}

int main () {
    int s= 1;
    int &z=s;
    raw(s);
    raw(z);
    return 0;
}

输出是(如预期的那样):

1
0x7fff5ed36894
1
0x7fff5ed36894

它按我的预期工作,但我很好奇这是如何在内部实现的。是函数重载还是其他什么,或者其中一个函数是另一个函数的包装器以提供用户友好性,或者编译器自己进行转换?

4

3 回答 3

7

这是它在汇编器中的样子:

    int s= 1;
002044A8  mov         dword ptr [s],1  
    int &z=s;
002044AF  lea         eax,[s]  
002044B2  mov         dword ptr [z],eax  
    raw(s);
002044B5  lea         eax,[s]  
002044B8  push        eax  
002044B9  call        raw (020110Eh)  
002044BE  add         esp,4  
    raw(z);
002044C1  mov         eax,dword ptr [z]  
002044C4  push        eax  
002044C5  call        raw (020110Eh)  

LEA (in lea eax,[s]) 表示加载有效地址,因此您可以看到如何z有效地包含指向位置的指针s

在函数调用之前准备参数的推送指令清楚地表明,在这两种情况下,您都获得了(相同的)指针作为输入。

这是未优化的代码。

于 2013-07-06T18:47:19.813 回答
5

当编译器为您的程序生成代码时,当它看到&这是一个引用的说法时,它实际上会生成一个指针变量[或机器代码中类似于指针的东西]。

因此z,将保存 的地址s

当你调用raw(s)时,编译器会说“啊,所以 raw 的参数是一个引用,它意味着”的地址s。当你这样做raw(z)时,编译器会说“啊,我们已经有一个引用,所以让我们传递”的内容z,因为你s之前将它设置为,所以它与s.

这正是它应该的样子。

于 2013-07-06T15:17:26.127 回答
3

在内部这个

int s= 1;
int &z=s;
raw(s);
raw(z);

对此进行了优化:

int s = 1;
raw(s);
raw(s);

因为在您执行变量之后,int &z = s; 变量z将被别名为 s 以结束其生命周期。所以基本上它会和s一样。

于 2013-07-06T15:15:10.867 回答