Why does the std::move() work in c++?
Asked Answered
O

1

6

Following is the code snippet:

int i=0;
int&&k=std::move(i);

In c++ primer the move is

template <typename T>
typename remove_reference<T>::type &&move(T&& t)
{return static_cast<typename remove_reference<T>::type&&>(t);}

As far as i know,this std::move template will deduct a function like

int&& move(int& t){return static_cast<int&&>(t);}

As a comparison and to elaborate my question,consider an example like this:

 int test(int k){k=66;return k;}
 int k;
 int a=test(k);

The code above will be compiled as:

int temp;//the temporary object
temp=k;
int a=temp;

Similarly,i think the first code snippet will be compiled as:

int&& temp=0;
int&& k=temp;//oop!temp is an lvalue!

which seems wrong because temp is an lvalue,did i get something wrong?

Overbear answered 22/2, 2018 at 14:57 Comment(6)
I'm just curious, is there a special reason you ask this? Is it curiosity? Or is there some underlying problem with code you have that lead to this question? If the latter, perhaps it would be better to ask about that issue directly instead?Karl
@FrançoisAndrieux I've rectified.Overbear
Your first snippet is equivalent to int &&k = static_cast<int&&>(i);.Wulf
std::move is just a cast. It will cast an lvalue or rvalue to an rvalue.Hankins
@Someprogrammerdude No exact issue,i come across the question in the process of learning rvalue reference.Overbear
An rvalue reference is not necessarily an rvalue itself.Kumkumagai
B
4

Similarly,i think the first code snippet will be compiled as:

int&& temp=0;
int&& k=temp;//oop!temp is an lvalue!

You might be confusing type with value category.

Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.

int&&k=std::move(i); and int&& k=temp; are not identical. The return type of std::move is rvalue-reference and then what std::move returns is an rvalue (more precisely it's an xvalue), which could be bound to rvalue-reference. On the other hand temp is a named variable then it's always an lvalue, regardless of whether its type is int, int&, int&& etc. Lvalue can't be bound to rvalue-reference.

More infomations about lvalue:

The following expressions are lvalue expressions:

  • the name of a variable, ...

and xvalue(rvalue):

The following expressions are xvalue expressions:

  • a function call or an overloaded operator expression, whose return type is rvalue reference to object, such as std::move(x);
  • ...
  • a cast expression to rvalue reference to object type, such as static_cast<char&&>(x);
Backscratcher answered 22/2, 2018 at 15:5 Comment(12)
@Overbear It's an xvalue, which belongs to rvalues. And see my edited answer.Backscratcher
Seems peculiar to me.A value type of function is not equivalent to the return type of function?Does the c++ standard make this concept for move() specially to make move semantic legal?Or are there more examples of this?Overbear
or because the int&& temp ,temp is rvalue because it's a temporary object?Overbear
@Overbear Type and value category are different things. The return type of the function is int, what the function returns is a prvalue; similarly, int& => lvalue, int&& => xvalue. Same for the named variable temp, its type is int&&, and it's an lvalue. A named variable is always an lvalue, regardless of whether its type is int, int&, int&&, etc.Backscratcher
@Overbear i think it's because the int temp is actually a rvalue.Hydromel
@bigxiao Variables are not rvalues. Variables do not have value categories. Only expressions have value categories.Congratulant
A variable can be an xvalue if the form is m.a, where m is an xvalue, then a is also an xvalue. E.g. struct S { int i; } s; std::move(s).i, where i is an xvalue.Greenquist
@Congratulant Your statement is only half right.A variable also belongs to expressions.Expressions consist of one or more operands.Hydromel
@MárioFeroldi That's the expression, not the variable.Congratulant
@bigxiao I don't know what you mean by "a variable also belongs to expressions".Congratulant
@Congratulant like int i,i can be called as expressionHydromel
That's a good point, and in that case the type of the variable influences the value category of the expression.Congratulant

© 2022 - 2025 — McMap. All rights reserved.