I'm curious about that is there any practical difference between using std::move
to convert an l-value integer to r-value, and adding a 0
to that integer? or any other neutral arithmetic operation (multiplying by 1
, subtracting 0
, etc).
Adding 0
:
int f(int&& i){
i ;
return i;
}
int main(){
int x = 43;
f(x 0);
}
Using std::move
:
#include <iostream>
int f(int&& i){
i ;
return i;
}
int main(){
int x = 43;
f(std::move(x));
}
I know we cannot perform such neutral actions on all types, but my question is specially about integral numbers not other types.
CodePudding user response:
std::move(x)
and x 0
do not do the same thing.
The former gives you an rvalue (specifically xvalue) referring to x
. The latter gives you a rvalue (specifically prvalue) which (after temporary materialization) refers to a temporary object with lifetime ending after the full-expression.
So f(x 0);
does not cause x
to be modified, while f(std::move(x))
does.
Taking a rvalue-reference to an int
specifically is probably pointless. Moving and copying scalar types is exactly the same operation, so there is no benefit over just int&
.
And your function both returns the result by-value and tries to modify the argument. Typically, it should do only one of those things. If it takes a reference and modifies the argument it should either have void
return value or return a reference to the argument. If it ought to return the result by-value, then it doesn't need to be passed a reference and can just take a int
parameter. (It would be ok to both modify the argument and return by-value if the value returned was unrelated to the new value of the argument, e.g. as in std::exchange
returning the old value of the argument.)
CodePudding user response:
Is there a difference? Yes. This is easily demonstrating by adding one line to your examples.
First case:
int f(int&& i){
i ;
return i;
}
int main(){
int x = 43;
f(x 0);
return x; // New line that uses `x`
}
Exit code 43 because the value of x
was not changed.
Second case
#include <utility> // More precise header
int f(int&& i){
i ;
return i;
}
int main(){
int x = 43;
f(std::move(x));
return x; // New line that uses `x`
}
Exit code 44 because the value of x
was changed (inside f()
).
Admittedly, the second case looks questionable because it uses the value of x
after applying std::move
to x
. Then again, that is another reason there is a difference. The expression std::move(x)
implies that there is no further use for (the value of) x
after that expression, whereas there is no such implication from the expression x 0
.
but my question is specially about integral numbers not other types.
It seems kind of pointless to be concerned specifically with moving integers (or other primitive types). For simple types, moving is the same as copying. If it were not for class types, there would have been no reason to introduce rvalue references and move semantics to the language.