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

use*_*165 5 c++ rvalue c++11

我有一个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));
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*rey 7

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

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

在函数的实现中发生了什么是另一回事.考虑像这样的方法

void add_shape_twice(unique_ptr<Shape>&& shape)
{ 
  m_shapes.push_back(shape);
  m_shapes.push_back(shape);
}
Run Code Online (Sandbox Code Playgroud)

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

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