函数 Return Mechanism:Temporary 对象,R 值,L 值

Function Return Mechanism:Temporary object, R-Value, L-Value

从底层分析问题,当一个函数 returns 一个值时,它要么在 cpu 寄存器中返回,要么在先前分配在堆栈上的 space 中返回由来电者。 此时调用函数可以获取值并将其复制到其局部变量中。

int sum(int a,int b){return a + b;}

int main(){int risultato = sum(10,20);return 0;}

在这种情况下,求和函数 returns EAX 寄存器中的值。然后 main 函数将 eax 寄存器中的值复制到堆栈上的内存位置。

这才是真正发生的事情。

现在转到 C++ 的抽象,如果我尝试执行这样的操作: 总和 (10.20) = 4; 它给了我一个错误。 这是因为基本上函数不返回包含值的内存位置,而是返回值本身。 因此,作为右值,这将不可分配,因为不可能将一个值分配给另一个值。 当使用取消引用运算符 * 时,问题变得完全不同。 在这种情况下,它不会返回一个值,而是内存位置本身(左值),因此它是可分配的。

我写的对吗?

我们现在来看第二个例子。

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;}

在这种情况下,函数 returns 是一个对象。 如果我尝试执行这样的指令: 乐趣 ()。我 = 4;我总是出错。

我知道调用函数时会在堆栈上创建一个临时对象。 将函数返回一个对象,但不是作为变量(左值),而是作为一组值,无法将其中一个值赋值为 4.

这里的语句似乎也存在同样的问题:

class1(10,20).i = 4;

在这种情况下,我正在创建一个临时对象,我不明白为什么它不给我分配对象变量 i 的可能性,为什么在这种情况下它总是被解释为右值和不是左值? 我知道我所做的在实践中没有用,但这仍然是一个纯理论问题,我需要正确理解语言的语法。

你能评论我到目前为止所说的一切,表达你的观点,并尝试回答最后一个问题吗?

I know that what I am doing has no use in practice

这是您问题的答案:

Why in this case is it always interpreted as an r-value and not as an l-value?

如果编译器需要将其设为 L 值,则更难实现,并且由于它没有用,因此不值得麻烦。

有些东西只是为了方便编译器编写者。

Moving now to the abstraction of C ++, if I tried to do an operation like this: sum (10.20) = 4; it gives me an error. This is because basically the function is not returning the memory location in which the value is contained, but the value itself. Being therefore an r-value, this will not be assignable, since it is not possible to assign a value to another value. The issue becomes completely different when the dereferencing operator * is used. In this case, it will not be returned a value, but the memory location itself (l-value), which will therefore be assignable.

Is what I wrote correct?

有点。你说

This is because basically the function is not returning the memory location in which the value is contained

但事实并非如此。返回一个对象,该对象有一个值。使它成为右值的原因是函数“returns by value”(另一个名称是临时对象)。

Being therefore an r-value, this will not be assignable, since it is not possible to assign a value to another value

这仅适用于内置类型。内置类型的赋值运算符要求被赋值的对象是左值。如果你有一个用户定义的类型(classstruct)那么你可以分配给一个右值。

In this case I am creating a temporary object, I don't understand why it doesn't give me the possibility to assign the object's variable i, why in this case is it always interpreted as an r-value and not as an l-value?

原因是 operator . 如果您调用它的对象是右值,那么您访问的成员将被视为右值。由于 i 是内置类型和右值,因此您不能为其赋值。

@NathanOliver 回答了 C++ 抽象机部分。我将添加一个关于它如何映射到 asm 的注释。

Then the main function copies the value from the eax register into a memory location on the stack.

或者不是,如果优化编译器只是将 risultato 保存在像 EAX 这样的寄存器中。或者完全优化它,因为在这种情况下它未被使用。

在抽象 C 中,每个对象都有一个内存地址(register int foo 变量除外),但在实践中,除非您禁用优化变量,否则只有在编译器用完寄存器时才会有地址。

return值对象在EAX中是

请注意,主流 C++ 调用约定仅 return 寄存器中的平凡可复制对象。一个非平凡的构造函数或析构函数甚至会强制一个成员的结构由隐藏指针returned,以确保构造函数和析构函数具有一致的this。 (调用约定规则不能依赖于构造函数和析构函数的内容,只是是否定义了其中一个。)