【发布时间】:2020-01-02 16:35:53
【问题描述】:
从底层分析这个问题,当一个函数返回一个值时,它要么在 cpu 寄存器中返回,要么在调用者先前在堆栈上分配的空间中返回。 此时调用函数可以获取该值并将其复制到其局部变量中。
int sum(int a,int b){return a + b;}
int main(){int risultato = sum(10,20);return 0;}
在这种情况下,sum 函数返回 EAX 寄存器中的值。然后 main 函数将 eax 寄存器中的值复制到堆栈上的一个内存位置。
这就是真正发生的事情。
现在转到 C++ 的抽象,如果我尝试执行这样的操作: 总和 (10.20) = 4; 它给了我一个错误。 这是因为基本上该函数不是返回包含值的内存位置,而是返回值本身。 因此,作为一个 r 值,这将是不可分配的,因为不可能将一个值分配给另一个值。 当使用取消引用运算符 * 时,问题变得完全不同。 在这种情况下,它不会返回一个值,而是内存位置本身(左值),因此可以分配。
我写的对吗?
让我们现在来看第二个例子。
class class1 {public: int i; int b; class1(int i,int b) { this->i = i;this->b = b; }};
class1 fun() { class1 c(10,5); return c; }
int main() {fun().i = 4; return 0;}
在这种情况下,函数返回一个对象。 如果我尝试执行这样的指令: 乐趣 ()。我 = 4;我总是出错。
我知道在调用函数时会在堆栈上创建一个临时对象。 将函数返回一个对象,但不是作为变量(左值),而是作为一组值,不可能将其中一个赋值为 4。
这里的语句似乎也存在同样的问题:
class1(10,20).i = 4;
在这种情况下,我正在创建一个临时对象,我不明白为什么它不能让我分配对象的变量 i,为什么在这种情况下它总是被解释为 r 值而不是l 值? 我知道我所做的在实践中没有用,但这仍然是一个纯粹的理论问题,我需要正确理解语言的语法。
您能否评论我到目前为止所说的所有内容,表达您的观点并尝试回答最后一个问题?
【问题讨论】:
-
然后 main 函数将 eax 寄存器中的值复制到堆栈上的内存位置。 或者不,如果优化编译器只是将
risultato保存在类似的寄存器中EAX。或者完全优化它,因为在这种情况下它没有被使用。在抽象 C 中,每个对象都有一个内存地址(register int foo变量除外),但在实践中,除非您禁用优化变量,否则只有在编译器用完寄存器时才会有地址。
标签: c++ function assembly return-value