2009-12-23 17 views
5

me encuentro con este códigoAmpersand dentro fundición

int n1 = 10; 
int n2 = (int &)n1; 

No entiendo el significado de este casting, n2 no es de referencia desde la modificación n1 no refleja n1. Extrañamente, este código arroja un error de compilación en gcc, ya que las compilaciones son correctas en VC++.

¿Alguien sabe el significado de este casting?

+0

Mi C++ está oxidado, pero creo que un * se puede usar para asignar un int o tener una serie de entradas. Sin embargo, no sé qué significaría & en este caso. –

+2

¿Cuál es el tipo de n1? –

+0

"modificar n1 no refleja n1" ?? –

Respuesta

9

Suponiendo n2 es de algún tipo incorporado, el elenco de int & tipo realiza la reinterpretación de lvalue n1 (cualquiera que sea el tipo que tenía) como un valor-I de tipo int.

En el contexto de int n2 = (int &) n1 declaración, si n1 es por sí misma un valor-I de tipo int, el elenco es superfluo, cambia absolutamente nada. Si n1 es un valor l de tipo const int, entonces el molde simplemente descarta la constness, que también es superfluo en el contexto anterior. Si n1 es un valor izquierdo de algún otro tipo, el elenco simplemente reinterpreta memoria ocupada por n1 como un objeto de tipo int (esto se llama tipo de juegos de palabras). Si n1 no es un valor l, el código está mal formado.

Por lo tanto, en el código como int n2 = (int&) n1 el elenco de int & sólo no redundante (tiene algún efecto real) cuando no escriba juego de palabras, es decir, cuando n1 es un valor izquierdo de algún otro tipo (no int). Por ejemplo

float n1 = 5.0; 
int n2 = (int &) n1; 

lo que equivaldría a

int n2 = *(int *) &n1; 

y para

int n2 = *reinterpret_cast<int *>(&n1); 

hace falta decir que esta es una práctica bastante mala programación.

Esto es, por cierto, uno de los casos cuando se usa un molde de estilo C++ dedicado es muy preferido. Si el autor del código usó reinterpret_cast en lugar del estilo C, probablemente no tenga que hacer esta pregunta.

Por supuesto, si n1 es del tipo int, no hay una explicación significativa para este elenco. En ese caso, es, de nuevo, completamente superfluo.

P.S. También existe la posibilidad de que n2 sea una clase con operador de conversión sobrecargado al tipo int &, que es una historia totalmente diferente ... De todos modos, debe decir qué n2 es cuando hace preguntas como esa.

11

Este es un código C++ perfectamente válido y compila con g ++ 4.4.1. Crea una referencia temporal a n1 y luego utiliza el valor al que hace referencia esa referencia para inicializar n2.

Esto puede ser más fácil de ver si expresada como una función:

void f(int & n1) { 
    int n2 = n1; // initialise with valuue referred to by n1 
} 

cuenta que esto no es un código válido C, como C no soporta referencias.

+0

Diría que, en este contexto, solo es "prefecto" válido en situaciones en las que es superfluo, es decir, cuando 'n1' tiene el tipo' int'. Cuando no es superfluo, es un 'reinterpret_cast'. Por lo general, cuando necesita reinterpretar la memoria ocupada por otro objeto, el código resultante puede ser sintácticamente válido, pero lejos de ser perfecto, por así decirlo. – AnT

+0

Debo admitir, supuse que n1 era un int. Sin embargo, a menos que la OP respomde, es posible que nunca sepamos ... –

+1

¿Qué es una "referencia temporal"? –

0

Se compila en gcc también (intenté solo para estar seguro). Simplemente arroja n1 a una referencia.

1

Creo que es probablemente un error tipográfico en el código original.

GCC suele ser más pedante que VC++. Sin embargo, este código parece correcto a pesar de que está haciendo cosas innecesarias. Básicamente, se crea una referencia temporal para n1 y luego se utiliza el constructor de copia para crear una instancia de n2.

+0

operador =, ¿seguro? Y si es así, estarías equivocado. El código muestra una inicialización, no una asignación: son cosas diferentes en C++. –

+0

Verdadero, corrigiendo la respuesta. – rui

+0

'n2' tiene tipo' int'. Escriba 'int' no es un tipo de clase. No tiene constructor de copia. No tiene constructores en absoluto. – AnT

2
int main() 
{ 
     int n1 = 10; 
     int n2 = (int &)n1; 
     cout<<n2<<endl; 
} 

Imprime 10 como esperaba.
No hay problema con el elenco.
Simplemente crea una referencia temporal como lo sugiere el siguiente resultado:

int main() 
{ 
     int n1 = 10; 
     int n2 = (int &)n1; 
     n2 = 20; 
     cout<<n1<<endl; // print 10 and not 20. 
} 
+0

Entonces, ¿cómo es esto diferente a solo "int n2 = n1"? –

1

Se hace lo obvio. Transmita n1 a una referencia int, y luego asígnelo al int n2.

Y suponiendo que n1 es un int, debería compilar muy bien.

No se compilará si n1 es un valor r. Lo siguiente no se compilará, por ejemplo:

(int&)foo(); 
(int&)42; 
(int&) (x+y); // assuming x and y are int variables 
+0

El último compilará perfectamente bien. El elenco tiene una precedencia mayor que la suma. '(int &) x + y' significa' ((int &) x) + y'. – AnT

+0

Es cierto. Corregido ahora :) – jalf