问题描述
对于本地作用域中的任何对象,我的默认行为是将其设置为 const
.例如:
My default behaviour for any objects in local scopes is to make it const
. E.g.:
auto const cake = bake_cake(arguments);
我会尽量减少非功能性代码,因为这会提高可读性(并为编译器提供一些优化机会).因此,在类型系统中也反映这一点是合乎逻辑的.
I try to have as little non-functional code as I can as this increases readability (and offers some optimisation opportunities for the compiler). So it is logical to also reflect this in the type system.
但是,使用移动语义会产生问题:如果我的 cake
很难复制或无法复制并且我想在处理完之后将其传递出去怎么办?例如:
However, with move semantics, this creates the problem: what if my cake
is hard or impossible to copy and I want to pass it out after I'm done with it? E.g.:
if (tastes_fine(cake)) {
return serve_dish(cake);
}
据我了解复制省略规则,不能保证蛋糕
副本将被删除(但我不确定).
As I understand copy elision rules it's not guaranteed that the cake
copy will be elided (but I'm not sure on this).
所以,我必须将 cake
移出:
return serve_dish(std::move(cake)); // this will not work as intended
但是 std :: move
将会无济于事,因为它(正确)不会将 Cake const&
转换为 Cake&&
.即使对象的寿命非常接近其寿命.我们不能从我们承诺不会改变的东西中窃取资源.但这会削弱const正确性.
But that std::move
will do nothing useful, as it (correctly) will not cast Cake const&
to Cake&&
. Even though the lifetime of the object is very near its end. We cannot steal resources from something we promised not to change. But this will weaken const-correctness.
那么,我怎么也可以吃蛋糕呢?
(即,我如何才能具有const正确性,还可以从移动语义中受益.)
(i.e. how can I have const-correctness and also benefit from move semantics.)
推荐答案
我认为,至少使用标准的move构造函数和非 mutable的对象,无法从
成员.但是,可以有一个 const
对象移动 const
自动本地对象和应用 copy elision (即 NRVO ).就您而言,您可以按以下方式重写原始功能:
I believe it's not possible to move from a const
object, at least with a standard move constructor and non-mutable
members. However, it is possible to have a const
automatic local object and apply copy elision (namely NRVO) for it. In your case, you can rewrite your original function as follows:
Cake helper(arguments)
{
const auto cake = bake_cake(arguments);
... // original code with const cake
return cake; // NRVO
}
然后,在原始功能中,您只需调用:
Then, in your original function, you can just call:
return serve_dish(helper(arguments));
由于 helper
返回的对象已经是非常量右值,因此可以将其移出(如果适用,也可以将其删除).
Since the object returned by helper
is already a non-const rvalue, it may be moved-from (which may be, again, elided, if applicable).
此处是演示此方法的现场演示.请注意,在生成的程序集中没有调用复制/移动构造函数.
Here is a live-demo that demonstrates this approach. Note that there are no copy/move constructors called in the generated assembly.
这篇关于我应该将局部变量设为const还是可移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!