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?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405

1 Answers1

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);
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • @user9396941 It's an xvalue, which belongs to rvalues. And see my edited answer. – songyuanyao Feb 22 '18 at 15:16
  • 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? –  Feb 22 '18 at 15:29
  • or because the `int&& temp` ,temp is rvalue because it's a temporary object? –  Feb 22 '18 at 15:32
  • 2
    @user9396941 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. – songyuanyao Feb 22 '18 at 15:34
  • 1
    @user9396941 i think it's because the `int temp` is actually a rvalue. – choxsword Feb 22 '18 at 15:36
  • 1
    @bigxiao Variables are not rvalues. Variables do not have value categories. Only *expressions* have value categories. – Sneftel Feb 22 '18 at 15:47
  • 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. – Mário Feroldi Feb 22 '18 at 16:40
  • @Sneftel Your statement is only half right.A variable also belongs to expressions.Expressions consist of one or more operands. – choxsword Feb 23 '18 at 02:30
  • @MárioFeroldi That's the expression, not the variable. – Sneftel Feb 23 '18 at 06:27
  • @bigxiao I don't know what you mean by "a variable also belongs to expressions". – Sneftel Feb 23 '18 at 06:27
  • @Sneftel like `int i`,`i` can be called as expression – choxsword Feb 23 '18 at 12:25
  • That's a good point, and in that case the type of the variable influences the value category of the expression. – Sneftel Feb 23 '18 at 12:40