O que isso "Won't x be leaked"significa? O tipo de xé um tipo de dados integrado. Por que você não escolhe um exemplo melhor?
Nawaz
2
@Nawaz: O exemplo é perfeito do jeito que está. Quase toda vez que falo com alguém sobre goto, eles pensam que até mesmo as variáveis automáticas de duração do armazenamento são de alguma forma "vazadas". Que você e eu saibamos de outra forma é completamente fora de questão.
Lightness Races in Orbit
1
@David: Concordo que esta pergunta faz muito mais sentido quando a variável tem um destruidor não trivial ... e eu olhei na resposta de Tomalak e encontrei um exemplo assim. Além disso, embora um intnão possa vazar, pode estar vazando . Por exemplo: void f(void) { new int(5); }vazamentos e int.
Ben Voigt,
Por que não mudar a pergunta para algo como "No exemplo dado, o caminho de execução do código será transferido de f () para main () sem limpar a pilha e outras funcionalidades de retorno da função? Importaria se um destruidor precisasse ser chamado? É o mesmo em C? " Isso manteria a intenção da pergunta, ao mesmo tempo que evitaria os possíveis equívocos?
Jack V.
Respostas:
210
Aviso: Esta resposta refere-se a C ++ única ; as regras são bastante diferentes em C.
Não vai xvazar?
Não, absolutamente não.
É um mito que gotoé alguma construção de baixo nível que permite que você substitua os mecanismos de escopo embutidos do C ++. (Se houver alguma coisa, é longjmpque pode estar sujeito a isso.)
Considere a seguinte mecânica que evita que você faça "coisas ruins" com rótulos (o que inclui caserótulos).
1. Escopo do rótulo
Você não pode saltar entre as funções:
void f(){int x =0;goto lol;}int main(){
f();
lol:return0;}// error: label 'lol' used but not defined
[n3290: 6.1/1]:[..] O escopo de um rótulo é a função na qual ele aparece. [..]
2. Inicialização do objeto
Você não pode pular na inicialização do objeto:
int main(){goto lol;int x =0;
lol:return0;}// error: jump to label ‘lol’// error: from here// error: crosses initialization of ‘int x’
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 volta após uma variável inicializada com duração de armazenamento automático envolve a destruição de objetos 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 saltar para o escopo de um objeto, mesmo que não seja 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 objetos , que a linguagem pode manipular independentemente porque eles não requerem uma 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 forma que ignore as declarações com a inicialização. Um programa que salta de um ponto onde uma variável com duração de armazenamento automático não está no escopo para um ponto onde está no escopo é malformado, a menos que a variável tenha tipo escalar, tipo de classe com um construtor padrão trivial e um destruidor trivial, um Versão qualificada de cv de um desses tipos ou uma matriz de um dos tipos anteriores e é declarada sem um inicializador. [..]
struct T {
T(){ cout <<"*T";}~T(){ cout <<"~T";}};int main(){{
T t;goto lol;}
lol:return0;}// *T~T
[n3290: 6.6/2]:Ao sair de um escopo (embora realizado), os objetos com duração de armazenamento automático (3.7.3) que foram construídos naquele escopo são destruídos na ordem inversa de sua construção. [..]
Conclusão
Os mecanismos acima garantem que gotovocê não quebra o idioma.
Claro, isso não significa automaticamente que você "deveria" uso gotopara qualquer problema, mas não significa que ele não é tão "mal", como as ligações mito comum que as pessoas acreditam.
Você pode notar que C não impede que todas essas coisas perigosas aconteçam.
Daniel,
13
@Daniel: A pergunta e a resposta são muito específicas sobre C ++, mas é justo. Talvez possamos ter outro FAQ dissipando o mito de que C e C ++ são a mesma coisa;)
Lightness Races in Orbit
3
@Tomalak: Não acho que estamos discordando aqui. Muitas das respostas fornecidas no SO estão explicitamente documentadas em algum lugar. Eu estava apenas enfatizando que pode ser tentador para um programador C ver essa resposta e presumir que, se funciona em C ++, deve funcionar da mesma forma em C.
Daniel
2
Você também pode querer acrescentar que todas essas coisas de inicialização são as mesmas para rótulos de caso.
PlasmaHH
12
Uau, eu tinha acabado de presumir que a semântica do C ++ estava quebrada para goto, mas eles são surpreendentemente lógicos! Ótima resposta.
"Won't x be leaked"
significa? O tipo dex
é um tipo de dados integrado. Por que você não escolhe um exemplo melhor?goto
, eles pensam que até mesmo as variáveis automáticas de duração do armazenamento são de alguma forma "vazadas". Que você e eu saibamos de outra forma é completamente fora de questão.int
não possa vazar, pode estar vazando . Por exemplo:void f(void) { new int(5); }
vazamentos eint
.Respostas:
Aviso: Esta resposta refere-se a C ++ única ; as regras são bastante diferentes em C.
Não, absolutamente não.
É um mito que
goto
é alguma construção de baixo nível que permite que você substitua os mecanismos de escopo embutidos do C ++. (Se houver alguma coisa, élongjmp
que pode estar sujeito a isso.)Considere a seguinte mecânica que evita que você faça "coisas ruins" com rótulos (o que inclui
case
rótulos).1. Escopo do rótulo
Você não pode saltar entre as funções:
2. Inicialização do objeto
Você não pode pular na inicialização do objeto:
Se você voltar para a inicialização do objeto, a "instância" anterior do objeto será destruída :
Você não pode saltar para o escopo de um objeto, mesmo que não seja explicitamente inicializado:
... exceto para certos tipos de objetos , que a linguagem pode manipular independentemente porque eles não requerem uma construção "complexa":
3. O salto obedece ao escopo de outros objetos
Da mesma forma, objetos com duração de armazenamento automático não são "vazados" quando você está fora de seu escopo
goto
:Conclusão
Os mecanismos acima garantem que
goto
você não quebra o idioma.Claro, isso não significa automaticamente que você "deveria" uso
goto
para qualquer problema, mas não significa que ele não é tão "mal", como as ligações mito comum que as pessoas acreditam.fonte