Est-il vrai que goto
saute à travers des morceaux de code sans appeler des destructeurs et des choses?
par exemple
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Ne x
sera- t-il pas divulgué?
Est-il vrai que goto
saute à travers des morceaux de code sans appeler des destructeurs et des choses?
par exemple
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
Ne x
sera- t-il pas divulgué?
"Won't x be leaked"
dire? Le type de x
est un type de données intégré. Pourquoi ne choisissez-vous pas un meilleur exemple?
goto
, ils pensent que même les variables automatiques de durée de stockage sont en quelque sorte «fuites». Que vous et moi savons le contraire est tout à fait autre chose.
int
ne peut pas fuir, il peut fuir . Par exemple: void f(void) { new int(5); }
fuit un fichier int
.
Réponses:
Avertissement: cette réponse concerne uniquement C ++ ; les règles sont assez différentes en C.
Ne
x
sera- t-il pas divulgué?
Non, absolument pas.
C'est un mythe qui goto
est une construction de bas niveau qui vous permet de remplacer les mécanismes de portée intégrés de C ++. (Si quelque chose, c'est longjmp
peut-être sujet à cela.)
Considérez les mécanismes suivants qui vous empêchent de faire de «mauvaises choses» avec les étiquettes (qui incluent les case
étiquettes).
Vous ne pouvez pas sauter entre les fonctions:
void f() {
int x = 0;
goto lol;
}
int main() {
f();
lol:
return 0;
}
// error: label 'lol' used but not defined
[n3290: 6.1/1]:
[..] La portée d'une étiquette est la fonction dans laquelle elle apparaît. [..]
Vous ne pouvez pas sauter à travers l'initialisation d'objet:
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 vous revenez à l'initialisation de l'objet, alors "l'instance" précédente de l'objet est détruite :
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]:
[..] Le transfert hors d'une boucle, hors d'un bloc ou en arrière au-delà d'une variable initialisée avec une durée de stockage automatique implique la destruction d'objets avec une durée de stockage automatique qui sont dans la portée au point transféré mais pas au point transféré vers . [..]
Vous ne pouvez pas sauter dans la portée d'un objet, même s'il n'est pas explicitement initialisé:
int main() {
goto lol;
{
std::string x;
lol:
x = "";
}
}
// error: jump to label ‘lol’
// error: from here
// error: crosses initialization of ‘std::string x’
... sauf pour certains types d'objets , que le langage peut gérer indépendamment car ils ne nécessitent pas de construction "complexe":
int main() {
goto lol;
{
int x;
lol:
x = 0;
}
}
// OK
[n3290: 6.7/3]:
Il est possible de transférer dans un bloc, mais pas d'une manière qui contourne les déclarations avec l'initialisation. Un programme qui saute d'un point où une variable avec une durée de stockage automatique n'est pas dans la portée à un point où elle est dans la portée est mal formé sauf si la variable a un type scalaire, un type de classe avec un constructeur par défaut trivial et un destructeur trivial, un cv-qualifié de l'un de ces types, ou un tableau de l'un des types précédents et est déclaré sans initialiseur. [..]
De même, les objets avec une durée de stockage automatique ne sont pas «divulgués» lorsque vous goto
sortez de leur portée :
struct T {
T() { cout << "*T"; }
~T() { cout << "~T"; }
};
int main() {
{
T t;
goto lol;
}
lol:
return 0;
}
// *T~T
[n3290: 6.6/2]:
A la sortie d'un périmètre (quelle qu'en soit la réalisation), les objets à durée de stockage automatique (3.7.3) qui ont été construits dans ce périmètre sont détruits dans l'ordre inverse de leur construction. [..]
Les mécanismes ci-dessus garantissent que goto
cela ne vous permet pas de casser la langue.
Bien sûr, cela ne signifie pas automatiquement que vous « devrait » utiliser goto
pour un problème donné, mais il ne signifie pas qu'il est loin d'être aussi « mal » , comme les fils de mythe commun les gens à croire.