从我正在阅读的教科书中可以看出,对于具有返回值的函数,返回值用于在调用站点初始化临时值。
我想知道的是在或 之后在被调用的函数退出之后发生了什么?换句话说,如果我在被调用函数中定义了一个变量(比如一个int
),它会在初始化临时之前或之后被破坏吗?
答案 0 :(得分:3)
这是技术观点。对于语言律师来说,这可能不是很有趣,但对于其他人来说,这可能是有益的。
函数以分支指令精确结束,该指令将控制权转移回调用者。在此之前,被调用者具有完全控制权,在此之后,调用者可以完全控制CPU执行的操作。通常,只有一条CPU指令用于此控制传输。在X86-64上,那是ret
指令,PowerPC使用blr
,其他CPU有相同的其他名称。但这个名字并不重要。
在函数本身的责任范围内的任何事情都必须在此指令之前发生,任何被调用者的业务都不会发生在其他任何地方。
由于调用者不知道函数创建了哪些变量,因此调用者不能破坏它们。更一般地说,被调用者必须释放它为自己的目的分配的任何堆栈空间。因此,被调用者必须在退出之前通过发出ret
指令来执行此类清理。这意味着,在函数退出之前,任何局部变量都必须消失。
从函数返回结果时,事情要复杂一些:这需要调用者和被调用者进行协作。不同的调用约定之间的细节不同,但通常有两种情况:
返回值在寄存器中传递 在这种情况下,被调用者将返回值加载到一个众所周知的寄存器中,调用者将使用相同的寄存器来访问返回值。
返回值在堆栈上传递。 在这种情况下,被调用者将把要返回的数据放在调用者堆栈帧中的定义位置,并且调用者将在调用返回后检查函数结果的相同内存区域。
TL; DR:如果某些东西是函数责任,它必须在函数返回之前发生(=执行ret
指令)。释放堆栈空间并将数据返回给调用者是这样的责任。
答案 1 :(得分:1)
对于按值返回的函数,将在函数范围退出之前初始化调用站点的临时函数。否则,任何返回值都将被销毁,然后才能传递给调用站点。
答案 2 :(得分:0)
函数在返回语句后结束 在该范围内声明的变量将超出范围,除非将变量声明为静态,否则您将无法使用该变量