我应在何时声明我的职能为:
void foo(Widget w);
而不是:
void foo(Widget&& w);
?
假设这是唯一的重载(例如,我选择一个或另一个,而不是两个,没有其他重载)。不涉及模板。假设函数 foo
需要 Widget
的所有权(例如,const Widget&
不在本讨论范围之内)。我对这些情况之外的任何答案都不感兴趣。(关于 为什么,请参阅后面的附录,这些限制是问题的一部分。)
我和我的同事可以得出的主要区别是,rvalue 引用参数强制您显式地表示副本。调用方负责创建一个显式副本,然后在需要副本时用 std::move
传递该副本。在按值传递的情况下,副本的成本是隐藏的:
//If foo is a pass by value function, calling + making a copy:
Widget x{};
foo(x); //Implicit copy
//Not shown: continues to use x locally
//If foo is a pass by rvalue reference function, calling + making a copy:
Widget x{};
//foo(x); //This would be a compiler error
auto copy = x; //Explicit copy
foo(std::move(copy));
//Not shown: continues to use x locally
除了迫使人们明确地复制和改变在调用函数时得到的语法糖的数量之外,还有什么不同之处呢?他们对界面有什么不同的看法?它们之间的效率是高还是低?
我和我的同事们已经想到的其他事情:
gcc.godbolt.org
的链接,显示来自 gcc/clang 的优化生成的代码,而不是标准中的一行。我展示这一点的尝试可能无法成功地隔离行为: https://godbolt.org/g/4yomtt附录: 为什么我是不是把这个问题限制得太多了?
foo
需要拥有 Widget
(也就是没有 const Widget&
)-我们不是在讨论只读函数。如果该函数是只读的,或者不需要拥有或延长 Widget
的生命周期,那么答案就变成了 const Widget&
,这也是众所周知的,而且没什么意思。我还提到了为什么我们不想谈论过载。