Quelle est la raison technique pour laquelle il est considéré comme une mauvaise pratique d'utiliser le throw
mot clé C ++ dans une signature de fonction?
bool some_func() throw(myExc)
{
...
if (problem_occurred)
{
throw myExc("problem occurred");
}
...
}
noexcept
change- t-il quelque chose?Réponses:
Non, ce n'est pas considéré comme une bonne pratique. Au contraire, il est généralement considéré comme une mauvaise idée.
http://www.gotw.ca/publications/mill22.htm explique en détail pourquoi, mais le problème est en partie que le compilateur n'est pas en mesure de le faire appliquer, il doit donc être vérifié au moment de l'exécution, ce qui est généralement indésirable. Et ce n'est pas bien supporté en tout cas. (MSVC ignore les spécifications d'exception, à l'exception de throw (), qu'il interprète comme une garantie qu'aucune exception ne sera levée.
la source
Jalf y est déjà lié, mais le GOTW explique très bien pourquoi les spécifications d'exception ne sont pas aussi utiles qu'on pourrait l'espérer:
C'est exactement ce à quoi cela se résume, vous finirez probablement avec un appel à
terminate()
et votre programme mourra d'une mort rapide mais douloureuse.La conclusion de GOTW est:
la source
Pour ajouter un peu plus de valeur à toutes les autres réponses à cette question, il faut investir quelques minutes dans la question: Quelle est la sortie du code suivant?
Réponse: Comme indiqué ici , le programme appelle
std::terminate()
et donc aucun des gestionnaires d'exceptions ne sera appelé.Détails: La première
my_unexpected()
fonction est appelée, mais comme elle ne rejette pas de type d'exception correspondant pour lethrow_exception()
prototype de fonction, ellestd::terminate()
est finalement appelée. Donc, la sortie complète ressemble à ceci:la source
Le seul effet pratique du spécificateur throw est que si quelque chose de différent de
myExc
est levé par votre fonction,std::unexpected
il sera appelé (au lieu du mécanisme d'exception normal non géré).Pour documenter le type d'exceptions qu'une fonction peut lever, je fais généralement ceci:
la source
Lorsque les spécifications de projection ont été ajoutées au langage, c'était avec les meilleures intentions, mais la pratique a confirmé une approche plus pratique.
Avec C ++, ma règle générale est de n'utiliser que les spécifications de projection pour indiquer qu'une méthode ne peut pas lancer. Il s'agit d'une garantie solide. Sinon, supposez qu'il puisse lancer n'importe quoi.
la source
Eh bien, lors de la recherche sur cette spécification de lancement, j'ai lu cet article: - ( http://blogs.msdn.com/b/larryosterman/archive/2006/03/22/558390.aspx )
J'en reproduis une partie ici également, afin qu'il puisse être utilisé à l'avenir indépendamment du fait que le lien ci-dessus fonctionne ou non.
Lorsque le compilateur voit cela, avec l'attribut "throw ()", le compilateur peut complètement optimiser la variable "bar", car il sait qu'il n'y a aucun moyen de lever une exception à partir de MethodThatCannotThrow (). Sans l'attribut throw (), le compilateur doit créer la variable "bar", car si MethodThatCannotThrow lève une exception, le gestionnaire d'exceptions peut / dépendra de la valeur de la variable bar.
De plus, les outils d'analyse de code source comme prefast peuvent (et utiliseront) l'annotation throw () pour améliorer leurs capacités de détection d'erreurs - par exemple, si vous avez un try / catch et que toutes les fonctions que vous appelez sont marquées comme throw (), vous n'avez pas besoin de try / catch (oui, cela a un problème si vous appelez plus tard une fonction qui pourrait lancer).
la source
Une spécification de non-projection sur une fonction en ligne qui ne renvoie qu'une variable membre et qui ne pourrait pas lever des exceptions peut être utilisée par certains compilateurs pour effectuer des pessimisations (un mot inventé pour l'opposé des optimisations) qui peuvent avoir un effet néfaste sur les performances. Ceci est décrit dans la littérature Boost: Spécification d'exception
Avec certains compilateurs, une spécification de non-projection sur les fonctions non en ligne peut être bénéfique si les optimisations correctes sont faites et que l'utilisation de cette fonction a un impact sur les performances d'une manière qui la justifie.
Pour moi, il semble que l'utilisation ou non soit un appel lancé par un œil très critique dans le cadre d'un effort d'optimisation des performances, peut-être à l'aide d'outils de profilage.
Une citation du lien ci-dessus pour ceux qui sont pressés (contient un exemple de mauvais effets involontaires de spécification de lancer sur une fonction en ligne à partir d'un compilateur naïf):
la source