J'ai tendance à ajouter beaucoup d'assertions à mon code C++ pour faciliter le débogage sans affecter les performances des versions. Maintenant, assert
est une macro en C pur, conçue sans tenir compte des mécanismes du C++.
Le C++, quant à lui, définit std::logic_error
Cette erreur est destinée à être lancée dans les cas où il y a une erreur dans la logique du programme (d'où son nom). Lancer une instance pourrait bien être l'alternative parfaite, plus proche de C++, à assert
.
Le problème est que assert
y abort
Les deux terminent le programme immédiatement sans appeler les destructeurs, évitant ainsi le nettoyage, alors que lancer une exception manuellement ajoute des coûts d'exécution inutiles. Une façon de contourner ce problème serait de créer une macro d'assertion propre SAFE_ASSERT
qui fonctionne exactement comme son homologue en C, mais qui lève une exception en cas d'échec.
Je peux penser à trois opinions sur ce problème :
-
S'en tenir à l'affirmation de C. Comme le programme est terminé immédiatement, il importe peu que les modifications soient correctement déroulées. De plus, l'utilisation de
#define
en C++ est tout aussi mauvais. - Lancer une exception et l'attraper dans main() . Permettre au code de sauter les destructeurs dans n'importe quel état du programme est une mauvaise pratique et doit être évité à tout prix, tout comme les appels à terminate(). Si des exceptions sont levées, elles doivent être attrapées.
-
Lancez une exception et laissez-la terminer le programme. Une exception mettant fin à un programme est acceptable, et en raison de
NDEBUG
ce qui ne se produira jamais dans une version finale. La capture n'est pas nécessaire et expose les détails de l'implémentation du code interne à des tiers.main()
.
Existe-t-il une réponse définitive à ce problème ? Une référence professionnelle ?
Édité : Sauter les destructeurs n'est, bien sûr, pas un comportement indéfini.