Pregunta ¿Cuáles son los signos de la inicialización de cruces?


Considera seguir el 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:

  1. Que es crosses initialization?
  2. ¿Por qué el primer inicializador x + y pasar la compilación, pero el último falló?
  3. ¿Cuáles son los problemas de los llamados crosses initialization?

EDITAR:
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 el no-POD en la instrucción de conmutación de múltiples casos.

Gracias.


74
2018-03-06 13:53


origen


Respuestas:


La versión con int r = x + y; tampoco compilará

El problema es que es posible r para 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 leería int r;)

Lo mejor que puede hacer es limitar el alcance de la variable. De esa forma satisfarás 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):

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


85
2018-03-06 14:03



Deberías poner el contenido del case entre paréntesis para darle alcance, de esa manera puede 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;
};

33
2018-03-06 14:02



Es posible transferir a un bloque, pero no de una manera que puentee las declaraciones con la inicialización. Un programa que salta desde un punto donde una variable local con una duración de almacenamiento automática no está en el alcance hasta un punto donde está en el alcance está mal formado a menos que la variable tenga un tipo de 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.


2
2018-03-06 15:01



Te sugiero que promuevas tu r variable antes de la switch declaración. Si quieres usar una variable en el case bloques, (o el mismo nombre de variable pero diferentes usos), defínalo antes de la instrucción switch:

#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 la asignación local (a.k.a. empujando hacia la pila) en cada case bloquear.

Un inconveniente de este enfoque es cuando los casos "caen" en otros casos (es decir, sin utilizar break), ya que la variable tendrá un valor previo.


0
2018-03-06 15:09