Je le sais static_assert
fait des assertions au moment de la compilation et assert
- au moment de l'exécution, mais quelle est la différence dans la pratique? Pour autant que je comprends, au fond, ce sont des morceaux de code, comme
if (condition == false) exit();
static_assert
fonctionnera, ou niquementassert
?if
ne peut pas faire?Vous posez trois questions, je vais donc essayer de répondre à chacune d'elles.
static_assert
fonctionnera, ou niquementassert
?static_assert
est bon pour tester la logique dans votre code au moment de la compilation. assert
est bon pour vérifier un cas pendant l'exécution qui devrait toujours avoir un résultat, mais peut peut-être produire un résultat inattendu dans des circonstances imprévues. Par exemple, vous devez uniquement utiliser assert
pour déterminer si un pointeur passé dans une méthode est null
alors qu'il semble que cela ne devrait jamais se produire. static_assert
ne comprendrait pas cela.
if
ne peut pas faire?assert
peut être utilisé pour interrompre l'exécution du programme, vous pouvez donc utiliser un if
, un message d'erreur approprié, puis arrêter l'exécution du programme pour obtenir un effet similaire, mais assert
est un peu plus simple pour ce cas. static_assert
n'est bien sûr valable que pour la détection des problèmes de compilation alors qu'un if
doit être valide par programme et ne peut pas évaluer les mêmes attentes au moment de la compilation. (Un if
peut cependant être utilisé pour cracher un message d'erreur au moment de l'exécution.)
Pas du tout!
static_assert
est censé faire échouer compilation avec le message spécifié, tandis que le traditionnel assert
est censé mettre fin à l'exécution de votre programme.
OK, je vais mordre:
Seul static_assert
Fonctionne si vous voulez que la compilation s'arrête sans succès si une condition statique est violée: static_assert(sizeof(void*) != 3, "Wrong machine Word size");
* Seules les assertions dynamiques peuvent intercepter les conditions dynamiques: assert(argc == 1);
Les instructions simples if
doivent être valides et compilables; les assertions statiques provoquent des échecs de compilation.
Non.
*) Un exemple pratique pourrait être d'empêcher l'utilisation abusive de constructions de modèles génériques, telles que int x; std::move<int&&>(x)
.
Est-ce une mauvaise pratique de les utiliser?
En cas d'abus, oui, en particulier assert
.
Un abus dépend de l'activation de ces instructions assert
. Vous ne devez jamais dépendre de assert
pour faire quoi que ce soit, car le code peut être compilé avec NDEBUG
défini, puis assert
ne fait rien. Le code de production est souvent compilé avec NDEBUG
défini pour garantir que ces instructions assert
disparaissent.
À moins que vous n'écriviez un programme unique qui ne durera pas plus d'un jour ou deux, vous ne devriez pas utiliser pour valider la saisie de l'utilisateur. Les utilisateurs se moquent de l'endroit où le code a échoué et le message imprimé ressemble à une langue étrangère pour de nombreux utilisateurs. Il ne dit pas à l'utilisateur comment corriger l'erreur. C'est aussi très impitoyable, par conception. Le message émis en réponse à une erreur de saisie utilisateur doit être un message indiquant à l'utilisateur comment résoudre le problème. La meilleure action après le message est d'offrir à l'utilisateur un moyen de corriger l'erreur. Si cela ne peut pas être fait, et si la seule réponse viable est de mettre fin au programme, le programme doit se terminer proprement. De par sa conception, assert
n'entraîne pas un arrêt net. Il appelle abort()
plutôt que exit()
.
Une conséquence de abort()
sur de nombreuses machines est de produire un vidage de mémoire. Un vidage de mémoire est un excellent message d'erreur pour un programmeur. Avec un vidage de mémoire, un programmeur peut utiliser le débogueur pour voir ce qui s'est mal passé dans les moindres détails. Un inconvénient de abort()
est que les choses ne sont pas nettoyées. Abandonner "termine le programme sans exécuter de destructeurs pour les objets de durée de stockage automatique ou statique et sans appeler les fonctions passées à atexit()
."
Bottom line: Il est correct (et bon) d'utiliser assert
pour tester les erreurs de programmation, mais uniquement dans un cadre de non-production. Utilisez autre chose pour tester les erreurs utilisateur.
static_assert
est une directive du compilateur. Il vous permet de vérifier les informations de type lors de la compilation. Cela entraînera un échec de compilation et produira un message d'erreur qui, dans la plupart des IDE, sera détecté et affiché dans la fenêtre d'erreur de l'IDE.
static_assert(sizeof(int) == 4,"int should be 4 bytes");
assert
est pour l'exécution, vous pouvez vérifier la valeur d'une variable. Si l'assertion échoue, l'assertion se déclenchera. Cela entraînera une boîte de message d'erreur qui apparaîtra au moment de l'exécution dans certains systèmes d'exploitation (assert dépend de l'implémentation)
assert(("mypointer should never be null!", mypointer != nullptr));