Es cierto que goto salta a través de bits de código sin llamar a los destructores y cosas?
p.ej
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
¿No xse filtrará?
Es cierto que goto salta a través de bits de código sin llamar a los destructores y cosas?
p.ej
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
¿No xse filtrará?
"Won't x be leaked"significa? El tipo de xes un tipo de datos integrado. ¿Por qué no eliges un mejor ejemplo?
goto, piensa que incluso las variables de duración del almacenamiento automático se "filtran" de alguna manera. Que tú y yo sepamos lo contrario está completamente fuera del punto.
intno puede tener fugas, puede tener fugas . Por ejemplo: void f(void) { new int(5); }fugas an int.
Respuestas:
Advertencia: esta respuesta se refiere a C ++ solamente ; las reglas son bastante diferentes en C.
¿No
xse filtrará?
No absolutamente no.
Es un mito que gotoes una construcción de bajo nivel que le permite anular los mecanismos de alcance integrados de C ++. (En todo caso, es longjmpque puede ser propenso a esto).
Considere los siguientes mecanismos que le impiden hacer "cosas malas" con las etiquetas (que incluye caseetiquetas).
No puede saltar entre 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 aparece. [..]
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 retrocede a través de la inicialización del objeto, la "instancia" anterior del objeto se destruye :
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]:[..] La transferencia fuera de un bucle, fuera de un bloque o retrocediendo 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 están dentro del alcance en el punto transferido pero no en el punto transferido a . [..]
No puede saltar al alcance de un objeto, incluso si no está inicializado explícitamente:
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 para 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 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 con duración de almacenamiento automático no está dentro del alcance a un punto donde está dentro del alcance está mal formado a menos que la variable tenga un tipo escalar, un tipo de clase con un constructor predeterminado trivial y un destructor trivial, un versión calificada por cv de uno de estos tipos, o una matriz de uno de los tipos anteriores y se declara sin un inicializador. [..]
Del mismo modo, los objetos con una duración de almacenamiento automático son no "filtrado" cuando gotofuera 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 alcance (sin importar cómo se haya logrado), los objetos con duración de almacenamiento automático (3.7.3) que se han construido en ese alcance se destruyen en el orden inverso de su construcción. [..]
Los mecanismos anteriores aseguran que gotono le permita romper el lenguaje.
Por supuesto, esto no significa automáticamente que "debería" usarlo gotopara un problema dado, pero sí significa que no es tan "malvado" como el mito común hace creer a la gente.