简体   繁体   中英

difference between using std::move and adding 0 to the number?

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.

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, eg as in std::exchange returning the old value of the argument.)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM