c++ - 当一个类/结构在没有 RVO 的情况下返回时会发生什么?
问题描述
我知道 RVO 通常是可取的,但是如果不能应用它会发生什么?具体来说,生成的汇编代码如何将本地类/结构实例返回给它的调用者?
MyClass callee() {
MyClass a;
/* RVO is disabled */
return a;
}
void caller() {
/* RVO is disabled */
MyClass b = no_rvo();
}
在这种情况下,堆栈是什么样的?caller()
和分别在堆栈上callee()
分配空间,a
然后复制到?如果是这样,是否在完全减少堆栈指针的末尾的 RET 语句到它之前的值,或者在复制操作之后释放堆栈内存?b
a
b
callee()
a
解决方案
这取决于调用约定。但是所有 x86 32 位和 64 位调用约定都做出相同的选择,并将指向返回值的指针作为“隐藏”的第一个参数传递。
callee
仍然可以优化掉a
(除非有其他事情阻止这种情况发生)并且直接存储到该返回值指针中。
非平凡可复制类型可能需要在某些时候运行复制构造函数,并为a
.
但是回复:您的实际问题,启用优化后,调用者将&b
作为返回值指针传递。
在禁用优化的情况下,我想我已经看到一些编译器为单独的返回值临时创建空间,然后从那里复制,这对于可简单复制的类型来说是非常多余的。
从理论上讲,返回值指针可以指向堆栈内存以外的某个地方,例如,如果分配给static MyClass arr[10]
.
但它不能指向任何可以以任何其他callee
方式访问的东西,因为在 C++ 抽象机器中,返回值是一个单独的对象,在函数返回之前没有任何东西可以指向。
推荐阅读
- flutter - 在颤动中隐藏texfield光标
- sql - 计算一个sql查询占另一个查询的百分比?
- c - 在 /proc/kallsyms 中找不到静态函数 local_apic_timer_interrupt
- python - Pygame 在圆内绘制曲面
- mysql - Use jdbc to connect to remote mysql via ip, but the ip becomes another ip
- python - 使用哪个 `pandas` 测试库
- algorithm - 在设计复杂的应用程序时,就地算法的意义是什么?
- gitlab - Gitlab 跑步者在完成之前开始另一项工作
- python - 无法解密 _val for key=...、无效的令牌或值
- javascript - 使用 mongodb 在 GET 请求中编写 .find 查询的最佳方法是什么?