Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 双参数与移动语义_C++_Move Semantics - Fatal编程技术网

C++ 双参数与移动语义

C++ 双参数与移动语义,c++,move-semantics,C++,Move Semantics,假设我有以下foo功能: Widget foo(Widget lhs, Widget rhs) { return lhs.bar(rhs); } 然后我想把它用于双方相同的论点: Widget baz(Widget w) { return foo(w, w); } 碰巧小部件很大,我想避免有太多的副本。假设bar已就位,我可以执行以下操作: Widget baz(Widget w) { return foo(std::move(w), w); } Widget baz(Widg

假设我有以下
foo
功能:

Widget foo(Widget lhs, Widget rhs) {
  return lhs.bar(rhs);
}
然后我想把它用于双方相同的论点:

Widget baz(Widget w) {
  return foo(w, w);
}
碰巧小部件很大,我想避免有太多的副本。假设bar已就位,我可以执行以下操作:

Widget baz(Widget w) {
  return foo(std::move(w), w);
}
Widget baz(Widget w) {
  Widget w_bis(w);
  return foo(std::move(w), std::move(w_bis));
}
这只会复制一份。但我担心这是错误的代码,因为C++中没有指定参数传递顺序,我可能会给出一个从参数中移动的值。 相反,我做了以下工作:

Widget baz(Widget w) {
  return foo(std::move(w), w);
}
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个副本。

根据您的评论
假设,bar是一个就地函数,我想将其转换为更经典的数学运算符(无副作用)
,让我们从编写
operator+
operator+=
中得到启发:

foo
更改为通过常量引用获取
rhs
,并让编译器决定如何处理
lhs

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

现在,您原来的
baz
函数是正确的,并且在“同一对象”的情况下只复制了一个副本。

我认为这是最安全的方法。我暗自怀疑,至少需要对
bar
进行一次粗略的实现才能充分发挥作用。例如,如果它是非变异的,或者只变异
*此
,我们可以利用引用来避免复制。您确实需要修改函数中的
小部件
?你不能把它当作常量参考吗?比方说,
bar
是一个就地函数,我想把它转换成一个更经典的数学运算符(没有副作用)。我仍然有这样的复制省略的好处。