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));
}
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With