web-dev-qa-db-fra.com

jeter nouvelle std :: exception vs jeter std :: exception

en regardant du code je suis tombé sur:

throw /*-->*/new std::exception ("//...

et j'ai toujours pensé que vous n'aviez pas besoin/vous ne devriez pas utiliser new ici.
Quelle est la bonne façon de procéder, les deux sont-ils OK? Si oui, y a-t-il une différence?

BTW de ce que je peux voir tout en "grepping" avec PowerShell boost libs jamais utiliser throw new.

P.S. J'ai aussi trouvé du code CLI qui utilise throw gcnew. Est-ce que ça va?

102
NoSenseEtAl

La méthode classique pour lancer et intercepter des exceptions consiste à lancer un objet exception et à l'attraper par référence (généralement const référence). Le langage C++ nécessite que le compilateur génère le code approprié pour construire l'objet exception et le nettoie correctement au moment opportun.

Lancer un pointeur sur un objet alloué dynamiquement n'est jamais une bonne idée. Les exceptions sont supposées vous permettre d'écrire du code plus robuste face aux conditions d'erreur. Si vous lancez un objet d'exception de manière conventionnelle, vous pouvez être sûr que s'il est attrapé par une clause catch nommant le type correct, par un catch (...), il sera ensuite relancé ou non. détruit correctement au moment opportun. (La seule exception est qu'elle ne soit jamais attrapée mais qu'il s'agisse d'une situation irrécupérable, quelle que soit la façon dont vous la regardez.)

Si vous lancez un pointeur sur un objet alloué dynamiquement, vous devez vous assurer que, quelle que soit l'apparence de la pile d'appels, vous allez créer un bloc catch qui nomme le type de pointeur correct et qui contient le delete appel. Votre exception ne doit jamais être interceptée par catch (...), à moins que ce bloc ne relance l'exception qui est alors interceptée pour être un autre bloc catch qui traite correctement l'exception.

En pratique, cela signifie que vous avez utilisé la fonctionnalité de gestion des exceptions qui devrait faciliter l’écriture de code robuste et rendre très difficile l’écriture de code correct dans toutes les situations. Cela laisse de côté le problème selon lequel il sera presque impossible d'agir comme code de bibliothèque pour le code client qui n'attendra pas cette fonctionnalité.

81
CB Bailey

Pas besoin d'utiliser new lors de la levée d'une exception.

Ecrivez:

throw yourexception(yourmessage);

et attraper comme:

catch(yourexception const & e)
{
      //your code (probably logging related code)
}

Notez que yourexception devrait dériver de std::exception directement ou indirectement.

28
Nawaz

Lancer new std::exception est correct si le site d’appel attend un std::exception*. Mais personne ne s'attendra à attraper un pointeur sur une exception. Même si vous documentez que c'est ce que fait votre fonction et que les gens lisent la documentation, ils sont toujours susceptibles d'oublier et d'essayer d'attraper une référence à un std::exception objet à la place.

22
Hurkyl

Le C++ FAQ a une bonne discussion à ce sujet:

  1. https://isocpp.org/wiki/faq/exceptions#what-to-catch
  2. https://isocpp.org/wiki/faq/exceptions#catch-by-ptr-in-mfc

Fondamentalement, "à moins qu'il y ait une bonne raison de ne pas le faire, attrapez-le par référence. Évitez d'attraper par valeur, car cela entraîne la copie et le comportement de l'exemplaire est différent de celui qui a été lancé. Ce n'est que dans des circonstances très spéciales que vous devez attraper par pointeur. "

7
user1202136