该函数如何在c ++中返回工作

时间:2012-03-06 02:23:27

标签: c++ function

我想知道如果我调用函数f(3),编译器如何保存这个临时int;  

int f (int x) { return x; } 

以及编译器将如何解决这个问题:

int a=f(3);

就像做一个int a = x; (我知道x已经被破坏了)或者它确实创建了一个名为f(3)的临时变量,就像这样int f(3)=x;

int& a=f(3);

为什么这不起作用?

5 个答案:

答案 0 :(得分:6)

函数调用

编译器将执行以下操作之一:

  1. 在堆栈上推送参数并调用该函数
    • 对于比你更复杂的功能,通常会发生这种情况。
  2. 将参数加载到寄存器中并调用该函数
    • 这个可能在优化时发生,并且有足够的寄存器来保存需要传递的变量。
  3. 完全优化功能(内联)
    • 对于像你的情况那样的简单函数,一个理智的编译器将使用最基本的优化级别来执行此操作,这样就可以像执行int a = 3一样获得相同的程序集。
  4. C ++中的引用变量

    引用变量,在代码中声明为int &a的引用变量是“现有内存位置的不同名称”。因此,声明int &a不会为任何地方的int分配空间。它只是声明a来引用已经分配的内存位置。

    此位置可能是现有变量int b,因此您说:

    int b;
    int &a = b;
    

    此处,a将引用b引用的相同内容。 “现有对象的新名称”是一个很好的习惯用法。

    你可以得到幻想并说出int &a = array[5],以便a引用int数组array的第6个元素,或int &a = *(int*)0x12345678来引用特定的记忆位置,但我很离题。

    您的代码

    int &a = 3;
    

    无法工作,因为3是一个临时对象,在执行语句后会被遗忘。要理解这个问题,请从根本上考虑这个问题:如果a引用已经分配的内存位置,那么在执行语句int &a = 3之后它会引用什么,并且不再有临时对象3

    这也是函数中引用变量的常见问题:返回对函数本地对象的引用是未定义的行为......但我再次离题了。你总是必须有一个“活着的,分配的对象”供a引用,故事的结尾。

    对参考变量更深入

    这样的声明通常会发生什么
    int a = 3;
    

    是编译器生成代码(简化):

    1. 将常数3加载到寄存器
    2. 将寄存器加载到为
    3. 分配的内存位置

      重点是:在任何一种情况下,都没有为对象3分配长期内存位置,因此实际上无法使int &a引用此对象。< / p>

      “长期存储位置”表示将通过分配操作的位置。在分配操作之后,存储3的寄存器将被覆盖并重新使用 ,因此它在理论上甚至不符合int &a的目标(实际上,int &a }无论如何,只能用来指代内存位置,而不是寄存器。)

答案 1 :(得分:1)

  1. 这取决于调用约定。使用cdecl(这是常见的),该函数将在EAX寄存器中返回x。然后将其复制到分配给a
  2. 的寄存器中

    当然,优化编译器会优化整个过程:

    int x = 3;
    

    2。您不能引用对象生命周期已结束的内容。 x的对象生存期在函数执行时结束。

答案 2 :(得分:0)

任何合理的编译器都可以(并且会)转向

int a=f(3);

进入

int a=3;

调用最初会编译成类似于将返回地址压入堆栈,然后是参数;函数本身会编译弹出参数,弹出返回地址并再次推送参数,然后分支到返回地址。一个简单的优化器会检测到没有完成任何有用的工作,并优化整个过程。

答案 3 :(得分:0)

  1. 当调用函数f(3)时,调用语句的指令地址保存在寄存器中,指令指针跳转到函数f的第一个语句的地址。函数f的新堆栈帧也被压入堆栈。当函数调用返回时,将从f(3)为返回的int创建临时值,这是当你执行int x=f(3);时将分配给x的内容(因此f中的返回值是在临时中创建的,然后是复制到x)所以是的,正在为返回创建临时。为f(3)创建的堆栈也被销毁。

  2. int& a=f(3);不能作为参考。 Reference是别名。别名适用于已存在的内容。 f(3)返回要分配给变量的临时副本。由于在f(3)调用之后堆栈将消失,你无法真正为其分配引用。

答案 4 :(得分:0)

int& a=f(3); - 关于这一点的不好之处在于您正在创建对临时变量的引用。在函数退出时,引用所引用的数据已被清除,因此它现在是一个挂起引用。

在您概述的情况下,编译器可能只会将int a = f(3);视为int a = 3;,但您永远无法确定,因为最终这取决于特定的编译器以及它如何执行其优化。 / p>

相关问题