2010-09-21 10 views
5

En las sentencias del conmutador declaración-con-inicialización no es válido pero declara-y-luego-asignación está permitido. Como se muestra en el siguiente fragmento de código.Switch-Case: declaración-con-inicialización y declaración-y-luego-asignación

¿Cuál es la diferencia entre estos dos tipos de inicializaciones desde el lado del compilador? Y por qué el primer tipo de inicialización no es válido y el segundo tipo es válido.

switch(val) 
{ 
case 0: 
    int newVal = 42; //Invalid 
    break; 
case 1: 
    int newVal2;  //Valid 
    newVal2 = 42; 
    break; 
case 2: 
    break; 
} 
+0

¿Qué compilador estás usando? – NullUserException

+0

Visual Studio 2008 –

Respuesta

4

De hecho, ninguno de los dos es legal C++. No se puede declarar una variable en un caso a menos que el interruptor está en el ámbito:

switch(val) 
{ 
case 0: 
    { 
    int newVal = 42; // now valid 
    } 
    break; 
case 1: 
    { 
    int newVal2;  // still Valid 
    newVal2 = 42; 
    } 
    break; 
case 2: 
    break; 
} 

El hecho de que su compilador permite que el caso 1 es un defecto de su compilador, o posiblemente una extensión. Al menos, de acuerdo con el estándar.

+0

La declaración de 'int newVal2;' es válida porque no hay inicializador. –

9

Efectivamente, la regla es que no se puede saltar a un bloque después de una declaración que tiene una inicialización (o más allá de la declaración de una variable de tipo no POD). El estándar de C++ dice (C++ 03 §6.7):

Es posible transferir a un bloque, pero no de una manera que evite las declaraciones con la inicialización. Un programa que salta (77) desde un punto donde una variable local con duración de almacenamiento automática no está dentro del alcance hasta un punto en el que está dentro del alcance está mal formada a menos que la variable tenga el tipo POD (3.9) y se declare sin inicializador (8.5).

(*) La transferencia del estado de una declaración switch a una etiqueta case se considera un salto en este sentido.

int newVal = 42; es una declaración de que tiene un inicializador (la parte = 42). El programa está mal formado porque si val es 1 o 2, saltará al bloque de conmutadores después de la inicialización.

int newVal2; es también una declaración; porque int es un tipo de POD y la declaración no tiene inicializador, puede saltar esta declaración.

+0

+1: Estaba buscando esto pero no pude encontrarlo en el estándar – Chubsdad

+0

OK. Es así porque el Estándar C++ lo dice. Pero lo que es racional detrás de lo mismo. ¿Por qué el estándar lo dice? ¿No es extraño que int newVal = 42; no está permitido donde como int newVal; newVal = 42; ¿esta permitido? –

+0

@Dahiya: No es tan extraño; la inicialización y la asignación son cosas diferentes (son cosas muy diferentes para la mayoría de los tipos que no son POD, ya que los constructores participan en la inicialización). Considere, por ejemplo, si tiene un 'std :: string'; si salta sobre su declaración, la variable es accesible pero sus contenidos no están inicializados porque su constructor nunca fue llamado. –