112 votes

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

Y a-t-il une différence entre throw() et noexcept autrement qu'en étant contrôlé respectivement au moment de l'exécution et de la compilation ?

Cet article de Wikipédia sur le C++11 suggère que les spécificateurs de jet de C++03 sont dépréciés.
Pourquoi ? noexcept suffisamment capable de couvrir tout cela au moment de la compilation ?

[Note : J'ai vérifié cette question et cet article mais n'a pas pu déterminer la raison solide de la dépréciation].

8 votes

D'après ceci bel article également noexcept peuvent faire l'objet de contrôles d'exécution. La principale différence entre les deux est que le fait de casser noexcept causes std::terminate tout en brisant throw causes std::unexpected . Le déroulement de la pile est également légèrement différent dans ces cas.

0 votes

Il n'y a rien qui soit vérifié au moment de la compilation avec certaines spécifications d'exception et qui soit vérifié au moment de l'exécution avec d'autres. Il s'agit d'un mythe créé par les opposants aux spécifications d'exception du C++.

149voto

Nicol Bolas Points 133791

Les spécificateurs d'exception ont été dépréciés parce que les spécificateurs d'exception sont généralement une mauvaise idée . noexcept a été ajouté parce qu'il s'agit de la seule utilisation raisonnablement utile d'un spécificateur d'exception : savoir quand une fonction ne le fera pas lance une exception. Il s'agit donc d'un choix binaire : les fonctions qui lancent des exceptions et celles qui n'en lancent pas.

noexcept a été ajouté plutôt que de supprimer tous les spécificateurs de jet autres que throw() parce que noexcept est plus puissant. noexcept peut avoir un paramètre qui, à la compilation, se résout en un booléen. Si le booléen est vrai, alors la fonction noexcept bâtons. Si le booléen est faux, alors le noexcept ne tient pas et la fonction peut être rejetée.

Vous pouvez donc procéder de la manière suivante :

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

Fait CreateOtherClass lancer des exceptions ? Cela pourrait être le cas si T peut le faire. Comment le savoir ? En procédant de la manière suivante :

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

Ainsi, CreateOtherClass() est lancé si le constructeur par défaut du type donné est lancé. Cela résout l'un des principaux problèmes des spécificateurs d'exception : leur incapacité à se propager dans la pile d'appels.

Vous ne pouvez pas le faire avec throw() .

1 votes

+1 Réponse utile, pour moi en tout cas. Je suis toujours à la recherche d'une réponse qui explique pourquoi je voudrais utiliser noexcept . Je n'ai jamais utilisé throw() et j'essaie de déterminer si l'on peut utiliser la méthode de l'analyse de l'information. noexcept apporte réellement un avantage (autre que la documentation vérifiée par le compilateur).

0 votes

Je viens de trouver ceci stackoverflow.com/questions/10787766/ .

0 votes

@hmjd : " Je suis toujours à la recherche d'une réponse qui explique pourquoi je voudrais utiliser noexcept. " Vous ne trouverez pas de réponse à cette question ici, parce que c'est pas la question qui a été posée.

35voto

Charles Bailey Points 244082

noexcept n'est pas vérifié à la compilation.

Une implémentation ne doit pas rejeter une expression simplement parce que, lorsqu'elle est exécutée, elle lance ou pourrait lancer une exception que la fonction qui la contient n'autorise pas.

Lorsqu'une fonction déclarée noexcept o throw() tente de lancer une exception, la seule différence est que l'on appelle terminate et les autres appels unexpected et ce dernier type de gestion des exceptions a été abandonné.

1 votes

Mais si une fonction virtuelle a throw() / noexcept La vérification au moment de la compilation permet de s'assurer qu'un overrider a également.

2voto

ma13 Points 53

std::unexpected() est appelée par le système d'exécution 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::unexpected() peut également être appelé directement à partir du programme.

Dans un cas comme dans l'autre, std::unexpected appelle l'application std::unexpected_handler . La valeur par défaut std::unexpected_handler appels std::terminate .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X