-1

std::move() is stealing the string value whereas not an int, please help me.

int main()
{
    int i = 50;
    string str = "Mahesh";        
    int j = std::move(i);
    string name = std::move(str);       
    std::cout <<"i: "<<i<<" J: "<<j <<std::endl;        
    std::cout <<"str: "<<str<<" name: "<<name <<std::endl;
    return 0;        
}

Output

i: 50 J: 50
str: name: Mahesh

user17732522
  • 53,019
  • 2
  • 56
  • 105
Raju
  • 1,149
  • 1
  • 6
  • 19
  • 5
    A moved-from object is in an undetermined state. "Having exactly the same value as before" is one possible instance of undetermined state. Practically speaking, what exactly did you expect to happen to `i`, and why? – Igor Tandetnik Jul 19 '18 at 13:50
  • Thanks for your response, I wanted to know how they handled for primitive types. It looks likes there is some abstraction to what happens to a moved primitive types. – Raju Jul 19 '18 at 13:58
  • 2
    A primitive type is simply copied. `int j = std::move(i)` is exactly equivalent to `int j = i` – Igor Tandetnik Jul 19 '18 at 14:00

2 Answers2

2

std::move is a cast to an rvalue reference. This can change overload resolution, particularly with regard to constructors.

int is a fundamental type, it doesn't have any constructors. The definition for int initialisation does not care about whether the expression is const, volatile, lvalue or rvalue. Thus the behaviour is a copy.

One reason this is the case is that there is no benefit to a (destructive) move. Another reason is that there is no such thing as an "empty" int, in the sense that there are "empty" std::strings, and "empty" std::unique_ptrs

Caleth
  • 52,200
  • 2
  • 44
  • 75
1

std::move() itself doesn't actually do any moving. It is simply used to indicate that an object may be moved from. The actual moving must be implemented for the respective types by a move constructor/move assignment operator.

std::move(x) returns an unnamed rvalue reference to x. rvalue references are really just like normal references. Their only purpose is simply to carry along the information about the "rvalue-ness" of the thing they refer to. When you then use the result of std::move() to initialize/assign to another object, overload resolution will pick a move constructor/move assignment operator if one exists. And that's it. That is literally all that std::move() does. However, the implementation of a move constructor/move assignment operator knows that the only way it could have been called is when the value passed to it is about to expire (otherwise, the copy constructor/copy assignment operator would have been called instead). It, thus, can safely "steal" the value rather than make a copy, whatever that may mean in the context of the particular type.

There is no general answer to the question what exactly it means to "steal" a value from an object. Whoever defines a type has to define whether it makes sense to move objects of this type and what exactly it means to do so (by declaring/defining the respective member functions). Built-in types don't have any special behavior defined for moving their values. So in the case of an int you just get what you get when you initialize an int with a reference to another int, which is a copy…

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39