C ++编译器是否能够将RVO应用于虚拟功能?
在这种情况下:
class AbstractReader
{
//...
public:
virtual std::vector<float> getFloatVector() = 0;
//...
}
class XmlReader : public AbstractReader
{
//...
public:
virtual std::vector<float> getFloatVector()
{
std::vector<float> result;
//Do some parsing here...
return result;
}
//...
}
class BinaryReader : public AbstractReader
{
//...
public:
virtual std::vector<float> getFloatVector()
{
std::vector<float> result;
//Do some decoding here...
return result;
}
//...
}
RVO可以适用于return result;
行吗?我猜不会。
然后,在这种情况下,std::move(result)
是否有办法返回大型容器?
由于
答案 0 :(得分:4)
是的,编译器可以执行RVO。我编写了一些测试代码并通过godbolt运行:
struct M {
M();
M(const M&);
M(M &&);
~M();
double * ptr;
};
M getM();
struct A {
virtual M foo() = 0;
};
struct B : A {
virtual M foo() override;
};
M B::foo(){
M m;
return m;
}
struct C : B {
virtual M foo() override;
};
M C::foo(){
M m = getM();
return m;
}
A* getA();
int main(){
A* p = getA();
M m = p->foo();
}
g++ -O3
生成
B::foo():
pushq %rbx
movq %rdi, %rbx
call M::M()
movq %rbx, %rax
popq %rbx
ret
C::foo():
pushq %rbx
movq %rdi, %rbx
call getM()
movq %rbx, %rax
popq %rbx
ret
main:
subq $24, %rsp
call getA()
movq (%rax), %rdx
movq %rax, %rsi
movq %rsp, %rdi
call *(%rdx)
movq %rsp, %rdi
call M::~M()
xorl %eax, %eax
addq $24, %rsp
ret
反汇编中明显缺席的是对M
的副本或移动构造函数的任何调用。
此外,标准中设置复制省略标准的段落没有区分虚拟和非虚拟成员函数,只要满足复制省略的标准,return
语句的重载解析&#34 ;首先执行,好像对象是由右值&#34;指定。
也就是说,在一个函数中
M foo() {
M m = /*...*/;
return m;
}
如果由于某种原因无法进行复制省略,并且移动构造函数可用,return m;
将始终调用移动构造函数而不是复制构造函数。因此,如果要返回局部变量,则不需要使用std::move
作为return语句。
答案 1 :(得分:0)
如果你return std::move(result);
,你无法获得任何收益,而你可能会失败。所以不要这样做。
你无法获得任何东西,因为标准明确说明“如果满足RVO条件,或者你正在返回一个参数,首先尝试返回 rvalue ,只有当它不能编译时,返回as lvalue。所以,即使你return result;
,编译器强制首先尝试return std::move(result);
。
您可能会输,因为return std::move(result);
会特别阻止RVO(如果适用的话)。