双参数和移动语义
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" 的情况下只复制一份。
假设我有以下 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" 的情况下只复制一份。