Irá usar variables ​​de vazamento?

É verdade que goto pula através de bits de código sem chamar destruidores e coisas?

por exemplo

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

Não vai vazar x ?

Aviso: esta resposta refere-se apenas ao C ++; as regras são bem diferentes em C.


Não vai vazar x ?

Não, absolutamente não.

É um mito que goto é alguma construção de baixo nível que permite que você sobrescreva os mecanismos de escopo embutidos do C ++. (Se alguma coisa, é longjmp que pode ser propenso a isso.)

Considere os seguintes mecanismos que impedem que você faça “coisas ruins” com labels (o que inclui labels de case ).


1. Escopo do label

Você não pode pular entre as funções:

 void f() { int x = 0; goto lol; } int main() { f(); lol: return 0; } // error: label 'lol' used but not defined 

[n3290: 6.1/1]: [..] O escopo de um label é a function na qual ele aparece. [..]


2. Inicialização do object

Você não pode pular a boot do object :

 int main() { goto lol; int x = 0; lol: return 0; } // error: jump to label 'lol' // error: from here // error: crosses initialization of 'int x' 

Se você pular de volta a boot do object, a “instância” anterior do object será destruída :

 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]: [..] A transferência de um loop, de um bloco ou de uma variável inicializada com duração de armazenamento automática envolve a destruição de objects com duração de armazenamento automático que estão no escopo no ponto transferido mas não no ponto transferido para. [..]

Você não pode pular para o escopo de um object , mesmo que não tenha sido explicitamente 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' 

... exceto para certos tipos de object , que a linguagem pode manipular independentemente porque eles não exigem construção "complexa":

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

[n3290: 6.7/3]: É possível transferir para um bloco, mas não de uma maneira que ignora declarações com boot. Um programa que salta de um ponto em que uma variável com duração de armazenamento automático não está no escopo para um ponto em que está no escopo é malformada a menos que a variável tenha tipo escalar, tipo de class com um construtor padrão trivial e um destruidor trivial, versão qualificada em cv de um desses tipos, ou uma matriz de um dos tipos anteriores e é declarada sem um inicializador. [..]


3. Pular permanece pelo escopo de outros objects

Da mesma forma, objects com duração de armazenamento automático não são "vazados" quando você sai do seu escopo :

 struct T { T() { cout < < "*T"; } ~T() { cout << "~T"; } }; int main() { { T t; goto lol; } lol: return 0; } // *T~T 

[n3290: 6.6/2]: Ao sair de um escopo (porém realizado), os objects com duração de armazenamento automático (3.7.3) que foram construídos nesse escopo são destruídos na ordem inversa de sua construção. [..]


Conclusão

Os mecanismos acima garantem que o goto não permite que você quebre o idioma.

Claro, isso não significa automaticamente que você "deveria" usar goto para qualquer problema, mas significa que não é tão "mal" quanto o mito comum leva as pessoas a acreditar.