本文介绍了我应该将局部变量设为const还是可移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于本地作用域中的任何对象,我的默认行为是将其设置为 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还是可移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 07:53