我在Computer Systems a programmer perspective中读到,当用汇编代码编程时,关于调用者 - 被调用者协议的约定规定函数的返回值应存储在eax
(或类似函数)中{64}计算机中的rax
寄存器。
我猜这是在C语言编程时“在幕后”自动发生的事情,这意味着C编译器“知道”使用eax
寄存器来返回函数。
但是当返回的值是一个不适合32位eax
或64位rax
寄存器的大对象时,C ++会发生什么?显然你不能使用堆栈传递它,那么编译器如何处理大对象的按值返回操作?
别介意一个大对象,C编译器如何处理大结构的返回值?
是否将其保存在临时内存空间中并将其地址作为返回值返回?如果是这样,它必须预测在运行时对函数执行多少次调用,有时这是不可能的,不是吗?
答案 0 :(得分:21)
显然你无法通过堆栈传递这个......
实际上,理论上每当调用一个函数并且它的堆栈框架被容纳时,它也为返回对象腾出空间。然后由调用函数确保将返回值复制到其自己的堆栈帧中的某个位置,以便它可以保留它。
这直接对应于它在C和C ++中的工作方式。您有一个return ...;
语句,它将一些值复制到返回对象中。返回对象是一个临时对象,因此调用代码必须将其存储在某处,例如int value = foo();
。
但是,几乎没有必要为备用值保留空间。相反,调用函数为它腾出空间,被调用函数将返回值直接放在那里。这正是return value optimization是什么以及副本省略代表什么。
答案 1 :(得分:14)
显然你不能使用堆栈传递这个
你可以!诀窍是让调用者在堆栈上分配空间,然后让函数填充它。
本质上,该函数返回堆栈框架调用者部分的数据。
答案 2 :(得分:1)
您应该想象函数的返回值会进入堆栈,就像局部变量一样。并且,与局部变量一样,这可以进行优化(并且有一些约定取决于规定明确定义的行为的体系结构),因此小的返回值会进入寄存器而不是堆栈。