简体   繁体   中英

Why can't I pass an rvalue-reference as it is to another function in C++11?

I have a code:

void f(int&& i) {
  auto lambda = [](int&& j) { (void)j; }
  lambda(i);
}

int main() {
  f(5);
}

Clang++ gives an error: no known conversion from 'int' to 'int &&' for 1st argument

Why the i changes its type to int when being passed to the lambda() ?

i is of type int&& , that is, it's of type "rvalue reference to int ." However, note that i itself is an lvalue (because it has a name). And as an lvalue, it cannot bind to a "reference to rvalue."

To bind it, you must turn it back to an rvalue, using std::move() or std::forward() .

To expand a bit: the type of an expression and its value category are (largely) independent concepts. The type of i is int&& . The value category of i is lvalue.

There are two elements at work here:

  • Type : The parameter i has type int&& , or "rvalue reference to int ", where "rvalue reference" is the name for the && feature, allowing binding rvalues to a reference;

  • Value category : This is the key. i has a name and so the expression naming it is an lvalue , regardless of its type or what the standard committee decided to call that type. :)

(Note that the expression that looks like i has type int , not int&& , because reasons. The rvalue ref is lost when you start to use the parameter, unless you use something like std::move to get it back.)

i is a name, and any object accessed by name is automatically an LValue, even though your parameter is marked as an rvalue reference. You can cast i back to an rvalue by using std::move or std::forward

void f(int&& i) {
  auto lambda = [](int&& j) { (void)j; };
  lambda(std::move(i));
}

int main() {
  f(5);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM