enquanto olhava para algum código que encontrei:
throw /*-->*/new std::exception ("//...
e sempre pensei que você não precisa / não deveria usar new
aqui.
Qual é a forma correta, ambas estão OK, em caso afirmativo, há alguma diferença?
BTW pelo que eu posso ver enquanto "grepping" com PowerShell boost libs nunca use throw new
.
PS também achei algum código CLI que usa throw gcnew
. Tudo bem?
throw gcnew
que seria útil, por exemplo. se você deseja que o código gerenciado capture sua exceção. Alguém pode me corrigir sobre isso?System::Exception
geralmente é uma referência a um objeto gerenciado no heap com coleta de lixo. Sempre jogueigcnew
e pegueiSystem::Exception ^
. É claro que também usofinally
o tempo todo em C ++ / CLI, embora não costumas misturar exceções C ++ no mesmotry
bloco, não sei por quê.Respostas:
A maneira convencional de lançar e capturar exceções é lançar um objeto de exceção e capturá-lo por referência (geralmente
const
referência). A linguagem C ++ requer que o compilador gere o código apropriado para construir o objeto de exceção e para limpá-lo adequadamente no momento apropriado.Lançar um ponteiro para um objeto alocado dinamicamente nunca é uma boa idéia. As exceções devem permitir que você escreva um código mais robusto em face das condições de erro. Se você lançar um objeto de exceção da maneira convencional, pode ter certeza de que, se ele for capturado por uma cláusula catch que nomeia o tipo correto, por um
catch (...)
, se for lançado novamente ou não, será destruído corretamente no momento apropriado. (A única exceção é se ele nunca for detectado, mas esta é uma situação irrecuperável de qualquer maneira que você olhe para ela.)Se você lançar um ponteiro para um objeto alocado dinamicamente, terá que ter certeza de que, seja qual for a aparência da pilha de chamadas no ponto em que deseja lançar sua exceção, há um bloco catch que nomeia o tipo de ponteiro correto e tem a
delete
chamada apropriada . Sua exceção nunca deve ser capturada por, acatch (...)
menos que esse bloco lance novamente a exceção que é então capturada por outro bloco catch que lida corretamente com a exceção.Efetivamente, isso significa que você pegou o recurso de tratamento de exceções que deve tornar mais fácil escrever código robusto e dificultar a escrita de código correto em todas as situações. Isso é deixar de lado o problema de que será quase impossível agir como código de biblioteca para código cliente que não esteja esperando esse recurso.
fonte
Não há necessidade de usar
new
ao lançar exceção.Apenas escreva:
e pegue como:
Observe que
yourexception
deve derivarstd::exception
direta ou indiretamente.fonte
new
? por que derivamyourexception
destd::exception
?throw std::exception;
funciona? g ++ não parece compilar ...std::exception
é um tipo, e você não pode lançar um tipo , você tem que lançar um objeto . Portanto, a sintaxe deve ser esta:throw std::exception();
Isso irá compilar. Agora, quão bom isso é, é uma questão completamente diferente.O lançamento
new std::exception
está correto se o site da chamada espera capturar astd::exception*
. Mas ninguém espera pegar um ponteiro para uma exceção. Mesmo se você documentar isso é o que sua função faz e as pessoas lerem a documentação, elas ainda podem esquecer e tentar capturar uma referência a umstd::exception
objeto.fonte
new std::exception
está correto apenas se o site de chamada está esperando pegar um ponteiro E está esperando assumir o gerenciamento da exceção de alocação E nunca haverá casos em que sua função será chamada por algo que não captura explicitamente o ponteiro correto (catch(...)
ou nenhum manuseio), caso contrário, haverá um vazamento de objeto. Resumindo, isso pode ser aproximado como "nunca".O C ++ FAQ tem uma boa discussão sobre isso:
Basicamente, "a menos que haja um bom motivo para não fazer isso, pegue por referência. Evite capturar por valor, pois isso faz com que uma cópia seja feita e a cópia pode ter um comportamento diferente do que foi lançado. Somente em circunstâncias muito especiais você deve capturar por ponteiro. "
fonte
A
é diferente do tipo,A*
então, se eu fizerthrow A()
isso, NÃO posso pegarcatch(A* e)
, pois é um tipo completamente diferente.O operador new não pode garantir que nunca gerará uma exceção. Por esse motivo, usá-lo para lançar uma exceção "válida" (pretendida) produziria um código que não pode ser garantido contra travamento. Uma vez que pode haver apenas uma exceção por vez, e seu programa tenta lançar duas antes que qualquer uma delas possa ser capturada, a melhor coisa que uma implementação pode fazer é abortar imediatamente seu programa, por exemplo, chamando std :: terminate.
fonte