在没有RVO的情况下返回类/结构会怎样?

时间:2019-05-29 04:49:06

标签: c++ assembly x86 calling-convention

我了解RVO通常是可取的,但是如果不能应用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的堆栈内存?

1 个答案:

答案 0 :(得分:3)

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

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

非平凡可复制类型可能需要在某个时候运行copy-constructor,并运行a的析构函数。


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

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

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

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