当没有 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()
是否分别在栈上为a
和b
分配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.
之前没有任何东西可以指向的对象
我知道一般情况下 RVO 是可取的,但是当它不能应用时会发生什么?具体来说,生成的汇编代码如何 return 一个本地 class/struct 实例给它的调用者?
MyClass callee() {
MyClass a;
/* RVO is disabled */
return a;
}
void caller() {
/* RVO is disabled */
MyClass b = no_rvo();
}
在这种情况下堆栈是什么样的? caller()
和callee()
是否分别在栈上为a
和b
分配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.