Lvalues y rvalues

Las expresiones se pueden categorizar en una de las siguientes categorías de valores:

Valor L

Una expresión puede aparecer en el lado izquierdo de una expresión de asignación si la expresión no esconstcualificado.

""Xvalor

Una referencia rvalue que va a caducar.

""(Prvalue) rvalue

""Una expresión no xvalue que sólo aparece en el lado derecho de una expresión de asignación.

Los rvalues incluyen xvalues y prvalues. Lvalues y xvalues se pueden denominar glvalues.

Notas:

  • La clase ""(prvalue) rvalues puede estar calificada para cv, pero los rvalues que no son de clase ""(prvalue) no pueden estar calificados para cv.
  • Los valores ""y xvalues pueden ser de tipos incompletos, pero los valores rvalues de ""(prvalue) deben ser de tipos completos ovoidmostrado anteriormente.
Un objeto es una región de almacenamiento en la que se puede examinar y almacenar. Un lvalue o ""xvaluees una expresión que hace referencia a un objeto de este tipo. Un lvalue no permite necesariamente la modificación del objeto que designa. Por ejemplo, un objeto const es un lvalue que no se puede modificar. El término lvalue modificable se utiliza para enfatizar que el lvalue permite cambiar el objeto designado así como examinarlo. Los siguientes tipos de objeto son lvalues, pero no son lvalues modificables:
  • Un tipo de matriz
  • Un tipo incompleto
  • Un tipo calificado por const
  • Un tipo de estructura o unión con uno de sus miembros calificado como un tipo const
Puesto que estos lvalues no son modificables, no pueden aparecer en el lado izquierdo de una sentencia de asignación.

El término rvalue hace referencia a un valor de datos que se almacena en alguna dirección de la memoria. Un rvalue es una expresión que no puede tener un valor asignado. Tanto una constante literal como una variable pueden servir como rvalue. Cuando aparece un lvalue en un contexto que requiere un rvalue, el lvalue se convierte implícitamente en un rvalue. Sin embargo, lo contrario no es cierto: un rvalue no se puede convertir en un lvalue. Los rvalues siempre tienen tipos completos o el tipo void.

Sólo C C define un designador de función como una expresión que tiene un tipo de función. Un designador de función es distinto de un tipo de objeto o un lvalue. Puede ser el nombre de una función o el resultado de desreferenciar un puntero de función. El lenguaje C también diferencia entre su tratamiento de un puntero de función y un puntero de objeto.

C++ Por otro lado, en C++, una llamada de función que devuelve una referencia es un lvalue. De lo contrario, una llamada a función es una expresión rvalue. En C++, cada expresión produce un lvalue, un xvalue de "", un rvalue de ""(prvalue) o ningún valor.

Tanto en C como en C++, determinados operadores requieren lvalues para algunos de sus operandos. La tabla siguiente lista estos operadores y restricciones adicionales sobre su uso.
Operador Requisito
& (unario) El operando debe ser un valor L.
++ -- El operando debe ser un valor L. Esto se aplica a los formularios de prefijo y de postfijo.
= += -= *= %= <<= >>= &= ^= |= El operando izquierdo debe ser un lvalue.

Por ejemplo, todos los operadores de asignación evalúan su operando derecho y asignan ese valor a su operando izquierdo. El operando izquierdo debe ser un lvalue modificable o una referencia a un objeto modificable.

El operador de dirección (&) requiere un lvalue como operando mientras que los operadores de incremento (++) y decremento (--) requieren un lvalue modificable como operando. El ejemplo siguiente muestra expresiones y sus lvalues correspondientes.
Expresión Valor L
x = 42 x
*ptr = newvalue *ptr
a++ a
C++ int& f() La llamada de función a f()

C++ Inicio solo de C++11 .

Las expresiones siguientes son xvalues:

  • El resultado de llamar a una función cuyo tipo de retorno es un tipo de referencia rvalue
  • Una conversión a una referencia rvalue
  • Un miembro de datos no estático de un tipo no de referencia al que se accede a través de una expresión xvalue
  • Un puntero a una expresión de acceso de miembro en la que el primer operando es una expresión xvalue y el segundo operando es de un puntero a un tipo de miembro

Consulte el ejemplo siguiente:

int a;
int&& b= static_cast<int&&>(a);

struct str{
   int c;
};

int&& f(){
   int&& var =1;
   return var;
}

str&& g();
int&& rc = g().c;

En este ejemplo, el inicializador para la referencia rvaluebes un xvalue porque es el resultado de una conversión a una referencia rvalue. Una llamada a la funciónf()produce un xvalue porque el tipo de retorno de esta función es delint&&tipo. El inicializador para la referencia rvaluerces un xvalue porque es una expresión que accede a un miembro de datos no de referencia no estáticoca través de una expresión xvalue.

C++ Fin de C++11 solamente.

Información relacionada