I am trying to understand rvalue reference and move semantics. In following code, when I pass 10 to Print function it calls rvalue reference overload, which is expected. But what exactly happens, where will that 10 get copied (or from where it referred). Secondly what does std::move
actually do? Does it extract value 10 from i
and then pass it? Or it is instruction to compiler to use rvalue reference?
void Print(int& i)
{
cout<<"L Value reference "<<endl;
}
void Print(int&& i)
{
cout<<"R Value reference "<< endl;
}
int main()
{
int i = 10;
Print(i); //OK, understandable
Print(10); //will 10 is not getting copied? So where it will stored
Print(std::move(i)); //what does move exactly do
return 0;
}
Thanks.
In the case of a 10
, there will probably be optimisations involved which will change the actual implementation, but conceptually, the following happens:
A temporary int
is created and initialised with the value 10
.
That temporary int
is bound to the r-value reference function parameter.
So conceptually, there's no copying - the reference will refer to the temporary.
As for std::move()
: there may be some tricky bits related to references etc., but principally, it's just a cast to r-value reference. std::move()
does not actually move anything. It just turns its argument into an r-value, so that it can be moved from.
"Moving" is not really a defined operation, anyway. While it's convenient to think about moving, the important thing is l-value vs. r-value distinction.
"Moving" is normally implemented by move constructors, move assignment operators and functions taking r-value references (such as push_back()
). It is their implementation that makes the move an actual move - that is, they are implemented so that they can "steal" the r-value's resources instead of copying them. That's because, being an r-value, it will no longer be accessible (or so you promise the compiler).
That's why std::move()
enables "moving" - it turns its argument into an r-value, signalling, "hey, compiler, I will not be using this l-value any more, you can let functions (such as move ctors) treat it as an r-value and steal from it."
But what exactly happens, where that 10 will get copied (or from where it referred)
A temporary value is created, and a reference passed to the function. Temporaries are rvalues, so can be bound to rvalue references; so the second overload is chosen.
Secondly what
std::move
actually do?
It gives you an rvalue reference to its argument. It's equivalent (by definition) to static_cast<T&&>
.
Despite the name, it doesn't do any movement itself; it just gives you a reference that can be used to move the value.
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