我通常会了解一个函数如何通过值返回一个对象.但是我想在较低层次上理解它.装配水平合理.
我明白这个代码
ClassA fun(){ ClassA a; a.set(...); return a; }
在内部转变为
void fun(Class& ret){ ClassA a; a.set(...); ret.ClassA::ClassA(a); }
我还明白,有一些优化(如NRVO)可以生成以下代码,避免复制构造函数.
void fun(Class& ret){ ret.set(...); }
不过我的问题有点更基本.它与实际上与对象无关.它可能甚至是原始类型.
让我们说我们有这个代码:
int fun(){ return 0; } int main(){ fun(); }
我的问题是存储在内存中的返回对象在哪里.
如果我们看堆栈…有堆栈框架的主,然后堆栈框架的乐趣.返回对象是否存储在某些地址中,也许在两个堆栈帧之间?或者也许它存储在主堆栈帧中的某个位置(也可能是在生成的代码中通过引用传递的地址).
我已经考虑过了,第二个看起来更实用,但是我不明白编译器如何知道多少内存来推动主框架的堆栈?它是否计算什么是最大的回报类型和推,即使可能有一些浪费的记忆?还是动态地完成,只在调用函数之前分配这个空间?
解决方法
C语言规范没有指定这些低级细节.它们由每个C实现指定,实际实现细节因平台而异.
在几乎每种情况下,一个简单的本地类型的返回值都会返回到某个指定的cpu寄存器中.当一个函数返回一个类实例时,细节会有所不同,这取决于实现.有几种常见的方法,但是典型的情况是调用者负责在调用函数并传递附加的隐藏参数之前为堆栈中的返回值分配足够的空间到功能要复制的函数返回的值(或在RVO的情况下构造它).或者,该参数是隐式的,并且该函数可以在堆栈之后在调用堆栈帧之后找到返回值本身的空间.
给定的C实现还可能使用cpu寄存器来返回足够小以适应单个cpu寄存器的类.或者,也许有几个cpu寄存器被保留用于返回略大的类.
细节各不相同,您将需要查阅C编译器或操作系统的文档,以确定适用于您的具体细节.