双参数和移动语义

Twin arguments and move semantic

假设我有以下 foo 函数:

Widget foo(Widget lhs, Widget rhs) {
  return lhs.bar(rhs);
}

然后我想在两边使用相同的参数:

Widget baz(Widget w) {
  return foo(w, w);
}

正好Widget比较大,不想复制太多。假设 bar 就位,我可以执行以下操作:

Widget baz(Widget w) {
  return foo(std::move(w), w);
}

这只会复制一份。但我担心这是不正确的代码,因为 C++ 中未指定参数传递顺序,我可能会给出一个移出的参数。

我改为执行以下操作:

Widget baz(Widget w) {
  Widget w_bis(w);
  return foo(std::move(w), std::move(w_bis));
}

我是不是过于谨慎了?有更简单的方法吗?

注:foo的设计是为了让我在享受复制省略带来的好处的同时,写出更自然的表达式。 t = foo(foo(x,y), foo(std::move(t),z)) 只会执行所需的 3 个副本。

鉴于您的评论 Let say, bar is an in-place function that I would like to transform into a more classical mathematical operator (side-effect free),让我们从 operator+ 的写作方式中汲取灵感 operator+=:

更改foo以通过const引用获取rhs并让编译器决定如何处理lhs:

Widget foo(Widget lhs, const Widget& rhs)
{
  return lhs.bar(rhs);
}

现在你原来的 baz 函数都是正确的 在 "same-object" 的情况下只复制一份。