Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;函数返回大对象还是结构?_C++_C_Assembly - Fatal编程技术网

C++ C++;函数返回大对象还是结构?

C++ C++;函数返回大对象还是结构?,c++,c,assembly,C++,C,Assembly,我在书中读到,当使用汇编代码编程时,关于调用方-被调用方协议的约定规定,函数的返回值应存储在eax(或64位计算机中的模拟rax)寄存器中 我猜这是在用C编程时“幕后”自动发生的事情,这意味着C编译器“知道”使用eax寄存器处理函数返回的值 但是,当C++返回的值是不适合32位的 EAX 或64位 RAX登记器时,会发生什么?显然,您不能使用堆栈来传递它,那么编译器如何处理大对象的按值返回操作呢 不管是大对象,C编译器如何处理大结构的按值返回 它是否将其保存在临时内存空间中,并将其地址作为返回值

我在书中读到,当使用汇编代码编程时,关于调用方-被调用方协议的约定规定,函数的返回值应存储在
eax
(或64位计算机中的模拟
rax
)寄存器中

我猜这是在用C编程时“幕后”自动发生的事情,这意味着C编译器“知道”使用
eax
寄存器处理函数返回的值

<>但是,当C++返回的值是不适合32位的<代码> EAX <代码>或64位<代码> RAX登记器时,会发生什么?显然,您不能使用堆栈来传递它,那么编译器如何处理大对象的按值返回操作呢

不管是大对象,C编译器如何处理大结构的按值返回

它是否将其保存在临时内存空间中,并将其地址作为返回值返回?如果是这样,它必须预测在运行时要对函数进行多少次调用,有时这是不可能的,不是吗

很明显,你不能使用堆栈来传递它

实际上,该理论是,每当调用函数并容纳其堆栈框架时,它也会为返回对象腾出空间。然后由调用函数来确保返回值被复制到它自己的堆栈帧中的某个地方,以便它可以保留它

<>这直接对应于它在C和C++中的工作方式。您有一个
返回语句,它将一些值复制到返回对象中。返回对象是一个临时对象,因此调用代码必须将其存储在某个地方,例如
int value=foo()

然而,几乎没有必要为返回值保留空间。相反,调用函数为它腾出空间,被调用函数将返回值直接放在那里。这正是复制省略所代表的内容

显然,您无法使用堆栈传递此消息

你可以!诀窍是让调用方分配堆栈上的空间,并让函数填充它


本质上,函数返回堆栈帧中调用方部分的数据。

您应该想象函数的返回值进入堆栈,就像局部变量一样。而且,与局部变量一样,可以对其进行优化(有一些约定取决于规定了定义良好的行为的体系结构),以便小的返回值进入寄存器而不是堆栈。

“关于调用方-被调用方协议的约定状态[…]”,对于一个特定的平台,它确实是——而且它是一个非常普遍部署的平台——但这在很大程度上依赖于平台。在其他机器上,寄存器可能(即经常)有不同的名称,而其他堆栈可能会以不同的方式使用相同的寄存器。@402不是所有人吗?@402,我在linux ubuntu上使用C专用编译器(gcc)。@so.very.hmm。。。GCC是专用的C编译器?GCC的特点是它既是“GNU编译器集合”又是“GNU C编译器”。也就是说,gcc(编译器)是gcc(总体编译复合体)的一个子集。因此,当我们说,“编译器保存了一个临时副本…”时,它实际上会将其保存在调用方堆栈帧处的预先指定内存中?@So.very.year是的,前提是它执行RVO(不管过去多少年,任何编译器都会这样做)。但该对象不是临时对象,临时对象将被完全删除。它只是将值直接存储在调用函数将要存储结果的对象中。所以在
int value=foo()中
例如,
foo
函数将其结果直接存储在
value
中。必须注意的是,要使RVO工作,您不能将返回值包装在std::move()中,并且不能对返回值进行隐式转换(返回的对象必须与函数签名匹配)。