当没有 RVO 返回 class/struct 时会发生什么?

What happens when a class/struct is returned WITHOUT RVO?

我知道一般情况下 RVO 是可取的,但是当它不能应用时会发生什么?具体来说,生成的汇编代码如何 return 一个本地 class/struct 实例给它的调用者?

MyClass callee() {
    MyClass a;
    /* RVO is disabled */
    return a;
}

void caller() {
    /* RVO is disabled */
    MyClass b = no_rvo();
}

在这种情况下堆栈是什么样的? caller()callee()是否分别在栈上为ab分配space,然后a复制到b?如果是这样,callee() 末尾的 RET 语句是否将堆栈指针完全递减到之前的位置,或者 a 的堆栈内存是否在复制操作后释放?

这取决于调用约定。但是所有 x86 32 位和 64 位调用约定都做出相同的选择,并将指向 return 值的指针作为 "hidden" 第一个参数传递。

callee 仍然可以优化掉 a(除非有其他东西阻止这种情况发生)并直接存储到那个 return-value 指针中。

non-trivially-copyable 类型在某些时候可能需要 运行 copy-constructor,以及 a.

的析构函数

但是回复:您的实际问题,在启用优化的情况下,调用者会将 &b 作为 return-value 指针传递。

禁用优化后,我想我已经看到一些编译器为单独的 return-value 临时创建 space,然后从那里复制,这对于 trivially-copyable 类型来说是非常多余的。

理论上 return-value 指针可以指向堆栈内存以外的其他地方,例如如果分配给 static MyClass arr[10].

的元素

但它不能指向任何 callee 可以访问任何 other 方式的任何东西,因为在 C++ 抽象机中 return 值是一个单独的在函数 returns.

之前没有任何东西可以指向的对象