在没有 RVO 的情况下返回类/结构时会发生什么?

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

本文关键字:结构 什么 RVO 返回 情况下      更新时间:2023-10-16

我知道 RVO 通常是可取的,但是当它无法应用时会发生什么?具体来说,生成的程序集代码如何将本地类/结构实例返回给其调用方?

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

在这种情况下,堆栈是什么样子的?caller()callee()是否分别为堆栈上的ab分配空间,然后将a复制到b?如果是这样,callee()末尾的 RET 语句是将堆栈指针完全减少到以前的状态,还是在复制操作后释放a堆栈内存?

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

callee仍然可以优化a(除非其他事情阻止这种情况发生),并直接存储到该返回值指针中。

不可复制的类型可能需要在某个时候运行复制构造函数,以及用于a的析构函数。


但是回复:您的实际问题,启用优化后,调用方将传递&b作为返回值指针。

禁用优化后,我想我已经看到一些编译器为单独的临时返回值创建空间,然后从那里复制,这对于可复制的类型来说是非常多余的。

理论上,返回值指针可以指向堆栈内存以外的其他位置,例如,如果分配给static MyClass arr[10]的元素。

但它不能指向callee可以通过任何其他方式访问的任何内容,因为在C++抽象机器中,返回值是一个单独的对象,在函数返回之前没有任何内容可以指向它。