Primeiro, estou ciente de Por que não existe uma construção 'finalmente' em C ++? mas uma longa discussão de comentários sobre outra questão parece justificar uma pergunta separada.
Além do problema que finally
em C # e Java pode existir basicamente apenas uma vez (== 1) por escopo e um único escopo pode ter vários (== n) destruidores de C ++, acho que eles são essencialmente a mesma coisa. (Com algumas diferenças técnicas.)
No entanto, outro usuário argumentou :
... Eu estava tentando dizer que um dtor é inerentemente uma ferramenta para (Release semântica) e, finalmente, é inerentemente uma ferramenta para (Commit semântica). Se você não vê o porquê: considere por que é legítimo lançar exceções umas sobre as outras em blocos finalmente e por que o mesmo não é para destruidores. (Em certo sentido, trata-se de dados versus controle. Destrutores são para liberar dados, finalmente é para liberar controle. Eles são diferentes; é lamentável que o C ++ os una.)
Alguém pode esclarecer isso?
fonte
A
eB
. Se um encadeamento for lançado, a reversão daA's
transação não deve destruir os recursos alocadosB
, por exemplo - os estados do encadeamento são independentes um do outro e a memória persistente que permanece no heap é independente de ambos. No entanto, normalmente em C ++, a memória heap ainda está vinculada a objetos na pilha.std::vector
objeto pode viver na pilha, mas apontar para a memória na pilha - tanto o objeto de vetor (na pilha) quanto seu conteúdo (na pilha) seriam desalocados durante o desenrolar da pilha nesse caso, pois destruir o vetor na pilha invocaria um destruidor que libera a memória associada no heap (e também destrói esses elementos de heap). Normalmente, para segurança de exceção, a maioria dos objetos C ++ vive na pilha, mesmo que sejam apenas identificadores que apontam para a memória na pilha, automatizando o processo de liberação da memória da pilha e da pilha na pilha.Que bom que você postou isso como uma pergunta. :)
Eu estava tentando dizer que destruidores e
finally
são conceitualmente diferentes:finally
é para retornar ao chamador ( controle )Considere, digamos, este pseudocódigo hipotético:
finally
aqui está resolvendo inteiramente um problema de controle e não um problema de gerenciamento de recursos.Não faria sentido fazer isso em um destruidor por vários motivos:
logfile.print
fracassar, enquanto a destruição (conceitualmente) não pode fracassarAqui está outro exemplo, desta vez como em Javascript:
No exemplo acima, novamente, não há recursos a serem liberados.
De fato, o
finally
bloco está adquirindo recursos internamente para atingir seu objetivo, o que poderia falhar potencialmente. Portanto, não faz sentido usar um destruidor (se o Javascript tiver um).Por outro lado, neste exemplo:
finally
está destruindo um recursob
,. É um problema de dados. O problema não é devolver o controle corretamente ao chamador, mas evitar vazamentos de recursos.Falha não é uma opção e nunca deve (conceitualmente) ocorrer.
Cada lançamento de
b
é necessariamente associado a uma aquisição e faz sentido usar o RAII.Em outras palavras, apenas porque você pode usar para simular ou isso não significa que ambos são um e o mesmo problema ou que ambos são soluções apropriadas para os dois problemas.
fonte
finally
é usado principalmente para liberar recursos (que não são de memória) afeta isso?finally
.finally
cláusula. A visão de mundo do C ++ apresentaria uma classe que gerencia esse "recurso" de uma atribuição a uma variável pseudo-global. Que sentido conceitual isso faz? Mas os destruidores são o martelo do C ++ para a execução necessária do código de fim de bloco.A resposta do k3b realmente expressa bem:
Quanto a "recursos", gosto de me referir a Jon Kalb: RAII deve significar aquisição de responsabilidade é inicialização .
De qualquer forma, quanto ao implícito versus explícito, isso parece realmente ser:
Eu acho que é isso para a parte conceitual, ...
... agora há IMHO alguns detalhes interessantes:
fault
bloco para executar o código que só deve ser executado no caso de uma saída de escopo excepcional.SCOPE_EXIT
,SCOPE_FAIL
eSCOPE_SUCCESS
na biblioteca de loucuras . Consulte Andrei Alexandrescu: tratamento de erros no fluxo de controle C ++ / declarativo (realizado na NDC 2014 )Também não acho que o c'tor / d'tor precise conceitualmente "adquirir" ou "criar" qualquer coisa, além da responsabilidade de executar algum código no destruidor. Qual é o que finalmente também faz: execute algum código.
E, embora o código em um bloco finalmente possa certamente gerar uma exceção, isso não é suficiente para dizer que eles são conceitualmente diferentes acima de explícito versus implícito.
(Além disso, não estou convencido de que o código "bom" deva ser lançado finalmente - talvez essa seja outra questão.)
fonte
observer
exemplo que jogar seria uma péssima ideia.) Sinta-se à vontade para abrir um bate-papo, se quiser discutir mais sobre isso. Certamente foi divertido pensar nos seus argumentos. Felicidades.