返回由右值引用传递的参数

时间:2016-06-17 01:07:32

标签: c++ return move-semantics pass-by-rvalue-reference

如果我有课程A和功能

A f(A &&a)
{
  doSomething(a);
  return a;
}
A g(A a)
{
  doSomething(a);
  return a;
}

a返回f时会调用复制构造函数,但从g返回时会使用移动构造函数。但是,根据我的理解,f只能传递一个可以安全移动的对象(临时或标记为可移动的对象,例如,使用std::move)。有什么例子从f返回时使用移动构造函数是不安全的吗?为什么我们要求a拥有自动存储时间?

我阅读了答案here,但最佳答案仅显示规范在将a传递给函数体中的其他函数时不应允许移动;它没有解释为什么在返回g是安全的而对f是安全的。一旦我们到达return语句,a内就不再需要f

更新0

所以我理解临时表在完整表达结束之前是可以访问的。但是,从f返回时的行为似乎仍然违背了根深蒂固的语义,即移动临时或xvalue是安全的。例如,如果调用g(A()),临时值将移动到g的参数中,即使可能存在对某些临时存储的引用。如果我们使用xvalue调用g,也会发生同样的情况。由于只有temporaries和xvalues绑定到rvalue引用,所以从a返回时我们应该仍然移动f的语义似乎是一致的,因为我们知道a是临时传递的或xvalue。

1 个答案:

答案 0 :(得分:0)

短篇小说:它只取决于doSomething

中级故事:如果doSomething 从不更改a,则f是安全的。它接收一个右值引用并返回从那里移动的新临时值。

长篇故事:一旦doSomething在移动操作中使用a,事情就会变坏,因为在返回语句中使用它之前可能处于未定义状态 - 它将是在g中相同,但至少转换为右值引用应该是显式的

TL / DR:只要f内没有移动操作,gdoSomething都是安全的。不同之处在于,移动将在f中默默执行,而需要在g中显式转换为右值引用(例如,使用std::move)。