0

I have looked at other posts regarding std::move but those examples were a bit complicated for me to understand so I will try to explain my problem with a very simple example here.

void increaseNum(int num) {
    num += 1;
}

int main() {
    int myNum {5};
    increaseNum(myNum); // Case-1
    increaseNum(std::move(myNum)) // Case-2
}

In Case-1 it does not change the value of myNum because I am passing it by value. It creates a copy of myNum inside increaseNum and changes the value of copy there. However, in Case-2 what I would expect is that I am saying to increaseNum "Hey, do not create a copy of myNum, instead take the ownership of that variable and change it, like pass by reference". When I print out myNum after Case-2, it is still 5 which confuses me.

Could someone please help me what I am missing here? Is giving std::move(variable) as function argument not the same as pass by reference? If not then why do we give std::move(variable) as function argument?

user17732522
  • 53,019
  • 2
  • 56
  • 105
test
  • 93
  • 1
  • 11
  • 2
    "_I would expect is that I am saying to increaseNum "Hey, do not create a copy of myNum, instead take the ownership of that variable and change it, like pass by reference"._", "_Is giving std::move(variable) as function argument not the same as pass by reference?_": Both are wrong. That's not what `std::move` does. "_If not then why do we give std::move(variable) as function argument?_": It is pointless for non-class types. It only matters if the function being called has a rvalue reference overload or, for pass-by-value, if the type has a move constructor. – user17732522 Apr 09 '23 at 13:01
  • 1
    Does this answer your question? [Why std::move() is not stealing an int value?](https://stackoverflow.com/questions/51424372/why-stdmove-is-not-stealing-an-int-value), https://stackoverflow.com/questions/3413470/what-is-stdmove-and-when-should-it-be-used. – user17732522 Apr 09 '23 at 13:03
  • 4
    Your expectations are wrong. Move semantics is not "like pass by reference". – Sam Varshavchik Apr 09 '23 at 13:04
  • 3
    Pass by value is determined by `int num` argument declaration in function signature. While `std::move` is mostly pointless for built-in and other trivially copyable types because it is an instrument to select r-value reference overloads which usually don't exists for those types. – user7860670 Apr 09 '23 at 13:07
  • 2
    Change your mental model of `std::move` this way: once an object has been `std::move`, it's in a state that is only suitable for destruction or re-assignment. So don't look at `myNum` after you move it, because it's tainted. (That's not actually what happens in this case with an `int`. But if you internalize the "moved object is now tainted", you will be better off.) – Eljay Apr 09 '23 at 13:11
  • 1
    @Eljay Actually you should change your mental model of `std::move` as well: `std::move` itself does literally nothing while the state of the object after passing produced r-value reference to the corresponding function may vary depending on the type of the object and the nature of function invoked, but must remain valid. – user7860670 Apr 09 '23 at 13:18
  • @user7860670 Do you mean that if the function takes r-value reference (i.e., increaseNum(int&& num) in my question), giving std::move as function variable works, or if it were a class which has move constructor then giving an already created instance of a class with std::move in the new constructor call of the same class for a new instance would invoke move constructor? – test Apr 09 '23 at 13:27
  • No, if function takes an r-value reference then it will be a pass-by-reference and no move constructors are going to be invoked. – user7860670 Apr 09 '23 at 13:35
  • @user7860670 • I understand how moving works. – Eljay Apr 09 '23 at 13:35
  • Let's assume a Widget class has both copy and move constructor. Which one is called in the secondInstance here: Widget instance; Widget secondInstance(std::move(instance)); – test Apr 09 '23 at 13:46
  • @Sarsa The move constructor. – john Apr 09 '23 at 14:02
  • @john But if we do it with a fundamental type like int, it copies like in my post above because it does not have any constructor or move semantics. Am I right? – test Apr 09 '23 at 14:23
  • @Sarsa I honestly don't know the legally correct answer to that. But in practice yes, any compiler is just going to copy the integer value, rather than artificially 'move' it. – john Apr 09 '23 at 14:26
  • Thank you so much to you @john and everyone. It was a very educational discussion we had here. – test Apr 09 '23 at 14:30

0 Answers0