这个功能背后的机制是什么?

时间:2013-07-06 15:12:25

标签: c++ function

我写了一个小程序:

#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

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

3 个答案:

答案 0 :(得分: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(在lea eax,[s]中)表示加载有效地址,以便您了解z如何有效地包含指向s位置的指针。

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

这是非优化代码。

答案 1 :(得分:5)

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

因此,z将保留s的地址。

当你调用raw(s)时,编译器会说“啊,所以raw参数是一个引用,意思是s的地址”。当您执行raw(z)时,编译器会说“啊,我们已经有了一个引用,所以我们只需要传递z”的内容,因为您之前将它设置为s,所以与s相同的地址。

这完全是应该的。

答案 2 :(得分:3)

内部

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

针对此进行了优化:

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

因为在int &z = s;之后z变量{{1}}将别名为s到其生命周期的结束。所以基本上它和s一样。