¿El uso de goto filtrará variables?


¿Es cierto que goto salta a través de bits de código sin llamar a destructores y cosas?

Por ejemplo

void f() {
   int x = 0;
   goto lol;
}

int main() {
   f();
lol:
   return 0;
}

No se filtrará x?

 89
Author: Marco Bonelli, 2011-09-07

1 answers

Advertencia: Esta respuesta pertenece a C++ solo ; las reglas son bastante diferentes en C.


No se filtrará x?

No, absolutamente no.

Es un mito que goto es una construcción de bajo nivel que le permite anular los mecanismos de alcance integrados de C++. (En todo caso, es longjmp que puede ser propenso a esto.)

Considere las siguientes mecánicas que le impiden hacer " cosas malas" con etiquetas (que incluye etiquetas case).


1. Ámbito de la etiqueta

No puedes saltar a través de funciones:

void f() {
   int x = 0;
   goto lol;
}

int main() {
   f();
lol:
   return 0;
}

// error: label 'lol' used but not defined

[n3290: 6.1/1]: [..] El alcance de una etiqueta es la función en la que parece. [..]


2. Inicialización de objetos

Usted no puede saltar a través de la inicialización de objetos :

int main() {
   goto lol;
   int x = 0;
lol:
   return 0;
}

// error: jump to label ‘lol’
// error:   from here
// error:   crosses initialization of ‘int x’

Si salta hacia atrás a través de la inicialización del objeto, entonces la "instancia" anterior del objeto es destruido:

struct T {
   T() { cout << "*T"; }
  ~T() { cout << "~T"; }
};

int main() {
   int x = 0;

  lol:
   T t;
   if (x++ < 5)
     goto lol;
}

// Output: *T~T*T~T*T~T*T~T*T~T*T~T

[n3290: 6.6/2]: [..] Transferencia fuera de un bucle, fuera de un bloque, o hacia atrás más allá de una variable inicializada con duración de almacenamiento automático implica la destrucción de objetos con duración de almacenamiento automático que se encuentran en alcance en el punto transferidos, pero no en el punto transferido a. [..]

Usted no puede saltar al ámbito de un objeto , incluso si no está explícitamente inicializado:

int main() {
   goto lol;
   {
      std::string x;
lol:
      x = "";
   }
}

// error: jump to label ‘lol’
// error:   from here
// error:   crosses initialization of ‘std::string x’

... excepto por ciertos tipos de objetos , que el lenguaje puede manejar independientemente porque no requieren una construcción "compleja":

int main() {
   goto lol;
   {
      int x;
lol:
      x = 0;
   }
}

// OK

[n3290: 6.7/3]: es posible transferir en un bloque, pero no en una forma que omite las declaraciones con inicialización. Un programa que salta desde un punto donde una variable con duración de almacenamiento automático no está en el alcance a un punto donde está en el alcance está mal formado a menos que la variable tiene tipo escalar, tipo de clase con un valor predeterminado trivial constructor y un destructor trivial, una versión calificada cv de uno de estos tipos, o una matriz de uno de los tipos anteriores y se declara sin inicializador. [..]


3. El salto se ajusta al alcance de otros objetos

Del mismo modo, los objetos con duración de almacenamiento automático son no "filtrados" cuando goto fuera de su alcance :

struct T {
   T() { cout << "*T"; }
  ~T() { cout << "~T"; }
};

int main() {
   {
      T t;
      goto lol;
   }

lol:
   return 0;
}

// *T~T

[n3290: 6.6/2]: Al salir de un ámbito (sin importar cómo se haya logrado), los objetos con almacenamiento automático duración (3.7.3) que se han construido en ese alcance se destruyen en el orden inverso de su construcción. [..]


Conclusión

Los mecanismos anteriores aseguran que goto no le permita romper el lenguaje.

Por supuesto, esto no significa automáticamente que "deberías" usar goto para cualquier problema dado, pero significa que no es tan "malo" como el mito común lleva a la gente a creer.

 201
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-11 01:01:05