web-dev-qa-db-fra.com

Différence entre le spécificateur C ++ 03 throw () C ++ 11 noexcept

Existe-t-il une autre différence entre throw() et noexcept en plus d'être vérifiée respectivement au moment de l'exécution et de la compilation?

Wikipedia C++ 11 l'article suggère que les spécificateurs de lancement C++ 03 sont déconseillés.
Pourquoi donc, noexcept est-il suffisamment capable de couvrir tout cela au moment de la compilation?

[Remarque: J'ai fait référence cette question et cet article , mais je n'ai pas pu obtenir la raison solide de la dépréciation.]

92
iammilind

Les spécificateurs d'exceptions ont été déconseillés parce que les spécificateurs d'exceptions sont généralement une idée terrible . noexcept a été ajouté car c'est la seule utilisation raisonnablement utile d'un spécificateur d'exception: savoir quand une fonction ne lèvera pas une exception. Ainsi, cela devient un choix binaire: les fonctions qui lanceront et les fonctions qui ne lanceront pas.

noexcept a été ajouté au lieu de simplement supprimer tous les spécificateurs de lancer autres que throw() car noexcept est plus puissant. noexcept peut avoir un paramètre qui se résout au moment de la compilation en booléen. Si le booléen est vrai, alors le noexcept colle. Si le booléen est faux, alors le noexcept ne colle pas et la fonction peut lancer.

Ainsi, vous pouvez faire quelque chose comme ceci:

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};

CreateOtherClass lève-t-il des exceptions? Il le pourrait, si le constructeur par défaut de T le pouvait. Comment le savons-nous? Comme ça:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};

Ainsi, CreateOtherClass() lancera ssi le constructeur par défaut du type donné lance. Cela corrige l'un des problèmes majeurs des spécificateurs d'exceptions: leur incapacité à propager la pile d'appels.

Vous ne pouvez pas faire cela avec throw().

118
Nicol Bolas

noexcept n'est pas vérifié au moment de la compilation.

Une implémentation ne doit pas rejeter une expression simplement parce que lorsqu'elle est exécutée, elle déclenche ou peut lever une exception que la fonction conteneur ne permet pas.

Lorsqu'une fonction déclarée noexcept ou throw() tente de lever une exception, la seule différence est que l'on appelle terminate et les autres appels unexpected et le ce dernier style de gestion des exceptions est en fait obsolète.

31
CB Bailey

std :: inattendu () est appelé par le runtime C++ lorsqu'une spécification d'exception dynamique est violée: une exception est levée à partir d'une fonction dont la spécification d'exception interdit les exceptions de ce type.

std :: inattendu () peut également être appelé directement à partir du programme.

Dans les deux cas, std :: inattendu appelle le std :: unlimited_handler actuellement installé. Le std :: unlimited_handler par défaut appelle std :: terminate.

1
ma13