Reputation: 1449
Consider the following c++ programs:
string construct(string&& s) {
// Passing a r-value reference as an argument to the assignment operator
string constructed = s;
return constructed;
}
int main() {
string original = "Hello";
string temp1 = construct(std::move(original));
printf("%s\n", original.c_str()); // Prints "Hello", so original has not changed
return 0;
}
Now a small change that I perform is calling std::move on an r-value reference argument:
string constructWithMove(string&& s) {
// Passing a cast to an r-value reference using r-value reference as an argument.
string constructed = std::move(s);
return constructed;
}
int main() {
string original = "Hello";
string temp = constructWithMove(std::move(original));
printf("%s\n", original.c_str()); // Prints "", original is set to the empty string, WHY???
return 0;
}
So it looks like casting an r-value reference to an r-value reference induces something peculiar. Why in the first case the original string retains its value but not in the second?
Upvotes: 3
Views: 3498
Reputation: 119847
string constructed = s;
This does not cause a move because s
is not an rvalue. It is an rvalue reference, but not an rvalue. If it has a name, it is not an rvalue. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression.
string constructed = std::move(s);
This causes a move because std::move(s)
is an rvalue: it's a temporary and its type is not lvalue reference.
There are no other moves in the program (std::move
is not a move, it's a cast).
Upvotes: 2
Reputation: 238301
What happens when std::move is called on a rvalue reference?
std::move
casts the argument into an rvalue reference, which it returns.
Is
std::move(r_value_reference_argument)
undefined
No.
// Prints "", original is set to the empty string, WHY???
What's happening here?
Because the result from std::move
is an r-value (x-value to be more specific). And being passed to a constructor of std::string
, it invokes the move constructor. You are observing a string that was moved from.
Note that this moving leaves the original string in an unspecified state. It is not guaranteed to be empty, nor even different from what it used to contain. Neither is it guaranteed to not be empty.
OK, but why in the first case the original string is not empty?
Because s
is an lvalue1, and therefore the copy constructor was used. The copy constructor leaves the original string unmodified.
1 Easy rule of thumb: If it is a name, then it is an l-value.
Upvotes: 7
Reputation:
// Prints "", original is set to the empty string, WHY???
Because you moved it.
Upvotes: 2