c++ c++11 rvalue-reference value-categories

c++ - ¿Cuál es la diferencia entre una referencia rvalue ordinaria y una devuelta por std:: forward?



c++11 rvalue-reference (2)

No puedo hacer esto

int &&q = 7; int &&r = q; //Error Message: //cannot convert from ''int'' to ''int &&'' //You cannot bind an lvalue to an rvalue reference

Si entiendo correctamente, al inicializar una referencia rvalue, también se inicializa una variable temporal. Así que int &&q = 7; puede ser considerado como:

int temp = 7; int &&q = temp;

Y cuando uso una referencia en el lado derecho, en realidad estoy usando el árbitro. Así que int &&r = q; puede ser considerado como:

int &&r = temp; //bind an lvalue to an rvalue reference, cause error, understandable

Así que arriba es como entiendo que ocurre el error del compilador.

¿Por qué agregar std::forward puede resolver eso?

int &&q = 7; int &&r = std::forward<int>(q);

Sé que std::forward siempre devuelve una referencia rvalue, ¿cómo es la referencia devuelta por std::forward diferente de int&&q ?


¿Cómo es la referencia devuelta por std::forward diferente de int&&q ?

Sus categorías de valor son diferentes. Y tenga en cuenta que los tipos y categorías de valor son cosas diferentes.

q es una variable con nombre, se califica como lvalue , por lo que no puede vincularse a rvalue reference.

(énfasis mío)

el nombre de una variable, una función, un objeto de parámetro de plantilla (desde C ++ 20) o un miembro de datos, independientemente del tipo, como std::cin o std::endl . Incluso si el tipo de la variable es referencia rvalue, la expresión que consiste en su nombre es una expresión lvalue;

Mientras que la referencia rvalue devuelta desde la función se califica como xvalue , que pertenece a rvalue .

una llamada de función o una expresión de operador sobrecargada, cuyo tipo de retorno es rvalue referencia a objeto, como std::move(x) ;


La diferencia entre las expresiones q y std::forward<int>(q) es que la primera es un lvalue, mientras que la última es un rvalue (de la categoría fundamental xvalue).

He abordado inquietudes similares en esta respuesta : el punto es que q como expresión es un valor l , porque tiene un nombre. std::forward<int>(q) (o el equivalente std::move(q) ) son expresiones que no tienen nombres, y como devuelven (sin nombre) las referencias de valores, son xvalues, que es una subcategoría de rvalue y por lo tanto puede vincularse a una referencia rvalue.