Considere el siguiente código:
#include <iostream>
using namespace std;
int main()
{
int x, y, i;
cin >> x >> y >> i;
switch(i) {
case 1:
// int r = x + y; -- OK
int r = 1; // Failed to Compile
cout << r;
break;
case 2:
r = x - y;
cout << r;
break;
};
}
G ++ se queja crosses initialization of 'int r'
. Mis preguntas son:
- ¿Qué es
crosses initialization
? - ¿Por qué el primer inicializador
x + y
pasa la compilación, pero el último falla? - ¿Cuáles son los problemas de los llamados
crosses initialization
?
Sé que debería usar corchetes para especificar el alcance de r
, pero quiero saber por qué, por ejemplo, por qué no se pudo definir no POD en una declaración de cambio de varios casos.
c++
initialization
Jichao
fuente
fuente
Respuestas:
La versión con
int r = x + y;
tampoco se compilará.El problema es que es posible
r
llegar al alcance sin que se ejecute su inicializador. El código se compilaría bien si eliminara el inicializador por completo (es decir, la línea se leeríaint r;
).Lo mejor que puede hacer es limitar el alcance de la variable. De esa forma, satisfará tanto al compilador como al lector.
switch(i) { case 1: { int r = 1; cout << r; } break; case 2: { int r = x - y; cout << r; } break; };
El Estándar dice (6.7 / 3):
fuente
int r = x + y
.Debes poner el contenido de
case
entre paréntesis para darle alcance, de esa manera puedes declarar variables locales dentro de él:switch(i) { case 1: { // int r = x + y; -- OK int r = 1; // Failed to Compile cout << r; } break; case 2: ... break; };
fuente
Es posible transferir a un bloque, pero no de una manera que omita las declaraciones con la inicialización. Un programa que salta desde un punto donde una variable local con duración de almacenamiento automático no está dentro del alcance a un punto en el que está dentro del alcance está mal formado a menos que la variable tenga un tipo POD y se declare sin un inicializador.
[Example: Code: void f() { // ... goto lx; // ill-formed: jump into scope of `a' // ... ly: X a = 1; // ... lx: goto ly; // ok, jump implies destructor // call for `a' followed by construction // again immediately following label ly } --end example]
La transferencia de la condición de una declaración de cambio a una etiqueta de caso se considera un salto en este sentido.
fuente
Le sugiero que promueva su
r
variable antes de laswitch
declaración. Si desea utilizar una variable en todos loscase
bloques (o el mismo nombre de variable pero diferentes usos), defínela antes de la declaración de cambio:#include <iostream> using namespace std; int main() { int x, y, i; cin >> x >> y >> i; // Define the variable before the switch. int r; switch(i) { case 1: r = x + y cout << r; break; case 2: r = x - y; cout << r; break; }; }
Uno de los beneficios es que el compilador no tiene que realizar una asignación local (es decir, empujar hacia la pila) en cada
case
bloque.Un inconveniente de este enfoque es cuando los casos "caen" en otros casos (es decir, sin usar
break
), ya que la variable tendrá un valor anterior.fuente