14

Desde hace un tiempo en algunos blogs aparecen dos términos que no termino de comprender: Rvalue y Lvalue. Sin tener claro el significado de ambos términos el contenido de determinados ejemplos se hace complicado de entender.

  1. ¿Qué diferencias hay entre un Rvalue y un Lvalue?
  2. ¿Cómo se puede identificar cada uno?
  3. ¿Qué se puede hacer y qué no con cada uno de ellos?
César
  • 16,990
  • 6
  • 37
  • 76
eferion
  • 49,291
  • 5
  • 30
  • 72

1 Answers1

11

En este artículo de MSDN hay una explicación breve y bastante clara. Te traduzco (énfasis mío):

Todas las expresiones de C++ son o un lvalue o un rvalue. Un lvalue es un objeto que persiste más allá de una expresión. Se puede pensar en un lvalue como en un objeto que tiene un nombre. Todas las variables, incluyendo las no modificables (const) son lvalues.

Un rvalue es un valor temporal que no persiste más allá de la expresión en la que se usa.

Para entender mejor la diferencia entre lvalue y rvalue, considera el siguiente ejemplo:

// lvalues_y_rvalues1.cpp
// compilar con: /EHsc
#include <iostream>
using namespace std;
int main()
{
   int x = 3 + 4;
   cout << x << endl;
}

Aquí x es un lvalue porque persiste más allá de la expresión que lo define. La expresión 3+4 es un rvalue porque se evalúa a un valor temporal que no persiste más allá de la expresión.

A continuación algunos ejemplos de usos incorrectos de lvalues y rvalues:

// lvalues_and_rvalues2.cpp
int main()
{
   int i, j, *p;

   // Uso correcto: la variable i es un lvalue.
   i = 7;

   // Uso incorrecto: el operando a la izquierda debe ser un lvalue (C2106).
   7 = i; // C2106
   j * 4 = 7; // C2106

   // Uso correcto: el puntero desreferenciado es un lvalue.
   *p = i; 

   const int ci = 7;
   // Uso incorrecto: la variable es un valor no modificable (C3892).
   ci = 9; // C3892

   // Uso correcto: el operador condicional devuelve un lvalue.
   ((i < 3) ? i : j) = 7;
}

TL;DR (no es parte del original): A un lvalue le puedes asignar un valor (si no es const). A un rvalue no, pero puedes usarlo como el valor que asignas a un lvalue.

Konamiman
  • 5,068
  • 2
  • 21
  • 44
  • ¿Cómo se traduciría TL;DR? ¿Quizá DL;NLL (demasiado largo, no lo leí)? – Konamiman Dec 11 '15 at 09:53
  • 2
    ¿que hay de xvalues, glvalues, y prvalues? como para completar la respuesta – rnrneverdies Dec 11 '15 at 11:30
  • @rnrneverdies Me ha parecido que no era necesario ya que en la pregunta no se mencionan. Pero sí, sería una buena adición. – Konamiman Dec 11 '15 at 11:37
  • @Konamiman Yo creo que en español lo suyo sería usar simplemente **resumen** o algo similar, TL;DR es una abreviatura común en inglés pero no tenemos un equivalente y forzarlo añade más confusión de la que soluciona. – Darkhogg Dec 11 '15 at 13:02
  • 1
    @rnrneverdies Quizás deberíamos llamarles *valores-i* y *valores-d* en castellano. [En las definiciones originales de estos términos en C](https://en.wikipedia.org/wiki/Value_(computer_science)#Assignment:_l-values_and_r-values), un ***l**-value* era un valor que aparecía—o que podía aparecer—a la izquierda (***L**eft* en inglés) de `=`, y un ***r**-value* era uno que aparecía a la derecha (***R**ight* en inglés). Bueno todo eso es una explicación fácil y corta, una que nos servía durante mucho años, pero en estos días C++ ha complicado esta historia bastante, como en todo lo demás. – tchrist Dec 11 '15 at 13:09
  • @Konamiman, no entendí este ejemplo... // Uso incorrecto: el operando a la izquierda debe ser un lvalue (C2106). 7 = i; // C2106 j * 4 = 7; // C2106 – Carlos Bello Jul 18 '20 at 21:48
  • 1
    @Retr0 `j` no está definido, se le está asignando un valor a una expresión. Es un uso incorrecto por que primero se le tiene que asignar un valor persistente a `j`. La manera correcta sería `j = 7 / 4`, la expresión a evaluar a la derechas. –  Jul 19 '20 at 12:38