首页 > 解决方案 > 当一个类/结构在没有 RVO 的情况下返回时会发生什么?

问题描述

我知道 RVO 通常是可取的,但是如果不能应用它会发生什么?具体来说,生成的汇编代码如何将本地类/结构实例返回给它的调用者?

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

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

在这种情况下,堆栈是什么样的?caller()和分别在堆栈上callee()分配空间,a然后复制到?如果是这样,是否在完全减少堆栈指针的末尾的 RET 语句到它之前的值,或者在复制操作之后释放堆栈内存?babcallee()a

标签: c++assemblyx86calling-convention

解决方案


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

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

非平凡可复制类型可能需要在某些时候运行复制构造函数,并为a.


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

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

从理论上讲,返回值指针可以指向堆栈内存以外的某个地方,例如,如果分配给static MyClass arr[10].

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


推荐阅读