Formulario erroneo:
int &z = 12;
Forma correcta:
int y;
int &r = y;
Pregunta :
¿Por qué es incorrecto el primer código? ¿Cuál es el " significado " del error en el título?
Formulario erroneo:
int &z = 12;
Forma correcta:
int y;
int &r = y;
Pregunta :
¿Por qué es incorrecto el primer código? ¿Cuál es el " significado " del error en el título?
(ostringstream() << "x=" << x).str()
Respuestas:
C ++ 03 3.10 / 1 dice: "Cada expresión es un valor l o un valor r". Es importante recordar que lvalor versus rvalority es una propiedad de las expresiones, no de los 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 rvalues.
El operador de dirección de 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 & = 12;
no es válido, el estándar dice que un literal de cadena es un valor l, otros literales son valores r.
std::string("meow")
construye un objeto de tipo std::string
y produce un valor r que designa este objeto, 1729
no tiene efectos secundarios y produce un valor 1729 como un valor de tipo int
.
"Lvalues name objects that persist beyond a single expression."
es 100% correcta. Por el contrario, su ejemplo (const int &)1
es incorrecto, porque NO es un objeto "nombrado".
int &z = 12;
En el lado derecho, int
se crea un objeto temporal de tipo a partir del literal integral 12
, pero el temporal no se puede vincular a una referencia no constante. De ahí el error. Es lo mismo que:
int &z = int(12); //still same error
¿Por qué se crea un temporal? Debido a que una referencia tiene que hacer referencia a un objeto en la memoria, y para que exista un objeto, primero debe crearse. Dado que el objeto no tiene nombre, es un objeto temporal . No tiene nombre. A partir 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
En aras de la integridad, me gustaría agregar que C ++ 11 ha introducido rvalue-reference, que puede vincularse a un objeto temporal. Entonces, en C ++ 11, puede escribir esto:
int && z = 12; //C+11 only
Tenga en cuenta que hay en &&
lugar de &
. También tenga en cuenta que const
ya no es necesario, aunque el objeto al que se z
une es un objeto temporal creado a partir de un literal integral 12
.
Dado que C ++ 11 ha introducido rvalue-reference , de int&
ahora en adelante se llama lvalue-reference .
12
es una constante en tiempo de compilació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;
void f( vector<int> const & )
, que es idiomática para pasar un vector que no se va a modificar. El problema ahora es que f( vector<int>(5) )
sería incorrecto y el usuario tendría que proporcionar una sobrecarga diferente, lo void f( vector<int> v ) { f(v); }
cual es trivial.
f( vector<int>(5) )
, el compilador crea un temporal y luego vincula la referencia a ese temporal, y de manera similar si hubo una conversión implícita de 5
directamente. Esto permite que el compilador genere una única firma para la función y habilita la implementación de la función por un solo usuario. A partir de ahí, se define un comportamiento similar para el resto de usos de referencias constantes por coherencia.
T const & r = *ptr;
, cualquier uso posterior de r
en la función puede ser reemplazado por *ptr
, y r
no necesita existir en tiempo de ejecución) o podría tener que implementarse manteniendo la dirección del objeto al que le asigna un alias (considere almacenar una referencia como miembro de un objeto), que se implementa como un puntero con referencia automática.
Estas son las reglas del lenguaje C ++:
12
) es un "rvalue"int &ri = 12;
está mal formadoTienes que entender que estas son reglas de C ++. Simplemente son.
Es fácil inventar un lenguaje diferente, digamos C ++ ', con reglas ligeramente diferentes. En C ++ ', estaría permitido crear una referencia no constante con un rvalue. Aquí no hay nada inconsistente o imposible.
Pero permitiría un código arriesgado donde el programador podría no obtener lo que pretendía, y los diseñadores de C ++ decidieron con razón evitar ese riesgo.
Las referencias son "punteros ocultos" (no nulos) a cosas que pueden cambiar (valores l). No puede definirlos como una constante. Debería ser algo "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 las #define x
obras solo están dentro del bloque que contiene la declaración de x
referencia.
const
:)
const