error: inicialización no válida de la referencia no constante del tipo ‘int &’ de un valor de r ‘del tipo’ int ‘

Formulario erroneo:

int &z = 12; 

Forma correcta:

 int y; int &r = y; 

Pregunta :
¿Por qué el primer código está mal? ¿Cuál es el ” significado ” del error en el título?

C ++ 03 3.10 / 1 dice: “Toda expresión es un valor l o un valor r”. Es importante recordar que lvalueness versus rvalueness es una propiedad de expresiones, no de objetos.

Lvalues ​​nombra objetos que persisten más allá de una sola expresión. Por ejemplo, obj , *ptr , ptr[index] y ++x son todos lvalues.

Los valores R son temporales que se evaporan al final de la expresión completa en la que viven (“en el punto y coma”). Por ejemplo, 1729 , x + y , std::string("meow") y x++ son todos valores r.

El operador de dirección requiere que su “operando sea un valor l”. si pudiéramos tomar la dirección de una expresión, la expresión es un valor l, de lo contrario es un valor r.

  &obj; // valid &12; //invalid 
 int &z = 12; 

En el lado derecho, se crea un objeto temporal de tipo int partir del literal integral 12 , pero el temporal no puede vincularse a la referencia no constante. De ahí el error. Es lo mismo que:

 int &z = int(12); //still same error 

¿Por qué se crea un temporal? Como una referencia tiene que hacer referencia a un objeto en la memoria, y para que exista un objeto, primero debe crearse. Como el objeto no tiene nombre, es un objeto temporal . No tiene nombre. De esta explicación, quedó bastante claro por qué el segundo caso está bien.

Un objeto temporal puede vincularse a una referencia constante, lo que significa que puede hacer esto:

 const int &z = 12; //ok 

Referencia C ++ 11 y Rvalue:

En aras de la integridad, me gustaría añadir que C ++ 11 ha introducido rvalue-reference, que puede vincularse a un objeto temporal. Entonces en C ++ 11, puedes escribir esto:

 int && z = 12; //C+11 only 

Tenga en cuenta que hay && intead de & . También tenga en cuenta que const ya no es necesario, aunque el objeto al que se une z es un objeto temporal creado a partir de literal-integral 12 .

Como C ++ 11 ha introducido la referencia-valor-real , int& ahora se llama en adelante referencia-valor .

12 es una constante en tiempo de comstackción que no se puede cambiar a diferencia de los datos a los que hace referencia int& . Lo que puedes hacer es

 const int& z = 12; 

El enlace de referencia no const y const sigue reglas diferentes

Estas son las reglas del lenguaje C ++:

  • una expresión que consiste en un número literal ( 12 ) es un “valorR”
  • no está permitido crear una referencia no constante con un valor r: int &ri = 12; está mal formado
  • está permitido crear una referencia constante con un valor r: en este caso, el comstackdor crea un objeto sin nombre; este objeto persistirá mientras exista la referencia en sí misma.

Tienes que entender que estas son reglas de C ++. Ellos simplemente son.

Es fácil inventar un lenguaje diferente, digamos C ++ ‘, con reglas ligeramente diferentes. En C ++ ‘, se permitiría crear una referencia no constante con un valor r. No hay nada inconsistente o imposible aquí.

Pero permitiría un código arriesgado en el que el progtwigdor podría no obtener lo que pretendía, y los diseñadores de C ++ decidieron evitar ese riesgo.

Las referencias son “punteros ocultos” (no nulos) a cosas que pueden cambiar (valores l). No puedes definirlos a una constante. Debería ser una cosa “variable”.

EDITAR::

estoy pensando en

 int &x = y; 

como casi equivalente a

 int* __px = &y; #define x (*__px) 

donde __px es un nombre nuevo, y #define x solo funciona dentro del bloque que contiene la statement de x referencia.