是否将rvalue作为参数传递给函数内的左值?

时间:2013-09-28 03:18:29

标签: c++ c++11 rvalue

我有一个View和一个Shape类,其中View“拥有”它的Shape对象。 我将其实现为unique_ptr的向量。 在函数View :: add_shape(std :: unique_ptr&& shape)中,我仍然需要在rvalue参数上使用std :: move来进行编译。为什么? (使用GCC 4.8)

#include <memory>
#include <vector>
using namespace std;

class Shape { };
class View
{
  vector<unique_ptr<Shape>> m_shapes;
  public:
  void add_shape(unique_ptr<Shape>&& shape)
  { 
    m_shapes.push_back(std::move(shape));// won't compile without the std::move
  }
};


int main()
{
  unique_ptr<Shape> ups(new Shape);
  View v;
  v.add_shape(std::move(ups));
}

2 个答案:

答案 0 :(得分:7)

是的,参数的右值参考仅用于从调用者的角度选择函数,它的行为类似于函数内的左值引用。

原因是你只允许移动一次值,并且认为自动保持参数的rvalue-ness被认为太危险了。参数类型表示此函数接受rvalue,并通过提供实际移动值的实现来潜在地使用它。通过重载这个版本的方法可以用于支持非移动版本。或者它只是说函数需要一个右值。

在函数的实现中发生的事情是另一回事。考虑像

这样的方法
void add_shape_twice(unique_ptr<Shape>&& shape)
{ 
  m_shapes.push_back(shape);
  m_shapes.push_back(shape);
}

如果shape作为参数仍然是右值参考:您可能会意外地将值移动两次。因为在现实世界中,函数可能更长,并且多次引用参数(显式地或在循环或包扩展中)是很常见的,所以错误的可能性将是巨大的。

即使我们都知道它并且永远不会忘记它,它也意味着我们需要抛弃rvalue-ness,这会使代码非常笨拙。我们会不断添加并删除 rvalue-ness。

答案 1 :(得分:4)

是的,在进入rvalue引用现在具有名称的功能后,将其视为左值。因此你必须move

void add_shape(unique_ptr<Shape>&& shape)
                                   ^^^^^

或按值传递:

void add_shape(unique_ptr<Shape> shape)