is rvalue passed as parameter treated as lvalue inside the function?

北战南征 提交于 2019-12-18 04:19:20

问题


I have a View and a Shape class where the View "owns" its Shape objects. I am implementing this as a vector of unique_ptr. In the function View::add_shape(std::unique_ptr&& shape), I still need to use std::move on the rvalue parameter to make it compile. Why? ( using 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));
}

回答1:


Yes, the rvalue reference from the parameter is only used to select the function from the caller's perspective, it behaves like an lvalue reference inside the function.

The reason is that you are only allowed to move a value once and it was deemed too dangerous to keep the rvalue-ness of a parameter automatically. The parameter type indicates that this function accepts an rvalue and makes potentially use of this by providing an implementation that actually moves the value. By overloading this version of the method can be used in favor of the non-moving version. Or it simply says that the function requires an rvalue.

What happens in the implementation of the function is another thing. Consider a method like

void add_shape_twice(unique_ptr<Shape>&& shape)
{ 
  m_shapes.push_back(shape);
  m_shapes.push_back(shape);
}

if shape as a parameter would remain an rvalue reference: You would have accidentally moved the value twice. Since in the real world functions may be longer and it's quite common to refer to the parameters multiple times (either explicitly or within a loop or pack expansion), the potential for errors would be enormous.

Even if we would all be aware of it and never forget about it, it would also mean that we need to cast away rvalue-ness and this would make the code quite clumsy. We would constantly be adding and removing rvalue-ness.




回答2:


Yes, after entering into the function that rvalue reference has a name now, so it's treat as lvalue. therefore you have to move it.

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

Or pass it by value:

void add_shape(unique_ptr<Shape> shape)


来源:https://stackoverflow.com/questions/19062853/is-rvalue-passed-as-parameter-treated-as-lvalue-inside-the-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!