web-dev-qa-db-fra.com

Quelle est la différence entre assert et static_assert?

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();
  • Quelqu'un peut-il me donner un exemple de l'endroit où niquementstatic_assert fonctionnera, ou niquementassert?
  • Font-ils quelque chose qu'une simple instruction if ne peut pas faire?
  • Est-ce une mauvaise pratique de les utiliser?
49
Oleksiy

Vous posez trois questions, je vais donc essayer de répondre à chacune d'elles.

  • Quelqu'un peut-il me donner un exemple de l'endroit où niquementstatic_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.

  • Font-ils quelque chose qu'une simple instruction 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.)

  • Est-ce une mauvaise pratique de les utiliser?

Pas du tout!

51
patrickvacek

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.

19
Nicola Musatti

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).

7
Kerrek SB

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.

4
David Hammen

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));
1
Yochai Timmer