通过右值引用返回是否更有效?
例如:
Beta_ab&& Beta::toAB() const {
return move(Beta_ab(1, 1));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
例如:
Beta_ab&& Beta::toAB() const {
return move(Beta_ab(1, 1));
}
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(3)
这会返回一个悬空引用,就像左值引用的情况一样。 函数返回后,临时对象将被破坏。 您应该按值返回
Beta_ab
,如下所示现在,它正确地将临时
Beta_ab
对象移动到函数的返回值中。 如果编译器可以,它将通过使用 RVO(返回值优化)来完全避免移动。 现在,您可以执行以下操作,它将把临时构造移动到ab中,或者执行RVO以完全省略移动或复制。 我建议您阅读 BoostCon09 Rvalue References 101 它解释了这个问题,以及如何( N)RVO 恰好与此相互作用。
在其他情况下,返回右值引用的情况是一个好主意。 假设您有一个经常在临时对象上调用的
getAB()
函数。 让它返回右值临时值的 const 左值引用并不是最佳选择。 您可以像这样实现它。请注意,在这种情况下,
move
不是可选的,因为ab
既不是本地自动右值,也不是临时右值。 现在,ref-qualifier&&
表示在右值临时变量上调用第二个函数,进行以下移动,而不是复制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 followingNow, 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 followingAnd 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.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 thisNote that
move
in this case is not optional, becauseab
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例如,在稍微不同的上下文中,它可以更加高效:
作为一个有趣的观察,在我的机器上
clang++ -O3
为上面的代码生成 54 条指令,而为常规std::min
。 但是,使用-O0
时,它会为上述代码生成 518 条指令,而常规std::min
则为 481 条指令。更新
对于不同意或不理解这个答案的人,我建议在编译器资源管理器又名 godbolt 中使用这个示例(https://godbolt.org) 在说有问题之前首先:
在
with_rvalue()
中,我们得到:在
without_rvalue()
中我们得到:正如您所看到的,当按右值返回时,我们避免了对象复制。 该原语的实用性是另一个主题,但这里有一个示例,说明按右值返回如何生成更优化的代码。
It can be more efficient, for example, in a bit different context:
As an interesting observation, on my machine
clang++ -O3
generates 54 instructions for code above versus 62 instructions for regularstd::min
. However, with-O0
it generates 518 instructions for code above versus 481 for regularstd::min
.UPDATE
For folks that disagree with or don't understand this answer, I would suggest to play with this sample in Compiler Explorer aka godbolt (https://godbolt.org) first before saying that something is wrong:
In
with_rvalue()
we get:In
without_rvalue()
we get:So as you can see, when returning by rvalue we avoid an object copy. Practicality of this primitive is another topic, but here you have an example of how returning by rvalue generates more optimal code.
正如已接受的答案中所指出和解释的那样,示例中的代码返回悬空引用,因为创建了临时引用。 C++26 草案在与 return 语句相关的部分中有以下段落(8.7.4.6):
因此,从 C++26 开始,示例中的代码似乎不再有效。
As noted and explained in the accepted answer, the code in the example returns dangling reference because a temporary is created. C++26 draft has the following paragraph in the section related to return statement (8.7.4.6):
So it seems the code in the example will not be valid anymore starting with C++26.