通过右值引用返回更有效吗?

2021-12-12 00:00:00 c++ c++11 rvalue-reference

例如:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

推荐答案

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

这将返回一个悬空引用,就像左值引用一样.函数返回后,临时对象将被销毁.您应该按值返回 Beta_ab,如下所示

This returns a dangling reference, just like with the lvalue reference case. After the function returns, the temporary object will get destructed. You should return Beta_ab by value, like the following

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

现在,它正确地将临时 Beta_ab 对象移动到函数的返回值中.如果编译器可以,它将通过使用 RVO(返回值优化)完全避免移动.现在,您可以执行以下操作

Now, it's properly moving a temporary Beta_ab object into the return value of the function. If the compiler can, it will avoid the move altogether, by using RVO (return value optimization). Now, you can do the following

Beta_ab ab = others.toAB();

它会将临时构造移动到 ab 中,或者执行 RVO 以完全省略移动或复制.我建议您阅读 BoostCon09 Rvalue References 101,它解释了这个问题,以及如何(N)RVO 恰好与此交互.

And it will move construct the temporary into ab, or do RVO to omit doing a move or copy altogether. I recommend you to read BoostCon09 Rvalue References 101 which explains the matter, and how (N)RVO happens to interact with this.

在其他情况下,您返回右值引用的情况是个好主意.想象一下,你有一个 getAB() 函数,你经常在临时调用它.让它为右值临时变量返回一个 const 左值引用并不是最佳选择.你可以这样实现它

Your case of returning an rvalue reference would be a good idea in other occasions. Imagine you have a getAB() function which you often invoke on a temporary. It's not optimal to make it return a const lvalue reference for rvalue temporaries. You may implement it like this

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

请注意,在这种情况下 move 不是可选的,因为 ab 既不是本地自动右值也不是临时右值.现在,ref-qualifier && 表示在右值临时变量上调用第二个函数,进行以下移动,而不是复制

Note that move in this case is not optional, because ab is neither a local automatic nor a temporary rvalue. Now, the ref-qualifier && says that the second function is invoked on rvalue temporaries, making the following move, instead of copy

Beta_ab ab = Beta().getAB();

相关文章