在这种情况下
struct Foo {};
Foo meh() {
return std::move(Foo());
}
我很确定此举是不必要的,因为新创建的 Foo
将是一个 xvalue。
但是在这样的情况下呢?
struct Foo {};
Foo meh() {
Foo foo;
//do something, but knowing that foo can safely be disposed of
//but does the compiler necessarily know it?
//we may have references/pointers to foo. how could the compiler know?
return std::move(foo); //so here the move is needed, right?
}
那里需要搬家,我想?
原文由 user2015453 发布,翻译遵循 CC BY-SA 4.0 许可协议
对于
return std::move(foo);
move
是多余的,因为 12.8/32:return foo;
是 NRVO 的情况,所以允许复制省略。foo
是一个左值。因此,为从foo
到返回值meh
的“复制”选择的构造函数如果存在,则必须是移动构造函数。添加
move
确实有潜在的影响:它可以防止移动被忽略,因为return std::move(foo);
不 符合 NRVO 的条件。据我所知,12.8⁄32 列出了左值的副本可以被移动替换的 唯一 条件。通常不允许编译器在复制后检测到未使用的左值(例如使用 DFA),并主动进行更改。我在这里假设两者之间存在可观察到的差异——如果可观察到的行为相同,则适用“as-if”规则。
因此,要回答标题中的问题,当您希望它被移动并且它不会被移动时,请在返回值上使用
std::move
。那是:考虑到这很繁琐,而且移动 通常 很便宜,您可能想说在非模板代码中您可以稍微简化一下。在以下情况下使用
std::move
:通过遵循简化的规则,您会牺牲一些移动省略。对于像
std::vector
这样的类型,移动起来很便宜,你可能永远不会注意到(如果你注意到了,你可以优化)。对于像std::array
类的移动成本很高的类型,或者对于您不知道移动是否便宜的模板,您更有可能担心它。