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 deint&&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
ostd::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.