[C++] Quelle est l'implication de la conversion de bool en C ++?


Answers

La performance est identique dans tous les domaines. Cela implique quelques instructions sur x86, peut-être 3 sur d'autres architectures.

Sur x86 / VC ++, ils le font tous

cmp DWORD PTR [whatever], 0
setne al

GCC génère la même chose, mais sans les avertissements (à tout niveau d'avertissement).

Question

[Cette question est liée à mais pas la même que celle-ci .]

Mon compilateur vous avertit de la conversion ou de la conversion implicite de certains types en booléen, alors que les conversions explicites ne produisent pas d'avertissement:

long t = 0;
bool b = false;
b = t;                    // performance warning: forcing long to bool
b = (bool)t;              // performance warning
b = bool(t);              // performance warning
b = static_cast<bool>(t); // performance warning
b = t ? true : false;     // ok, no warning
b = t != 0;               // ok
b = !!t;                  // ok

C'est avec Visual C ++ 2008 mais je soupçonne que d'autres compilateurs peuvent avoir des avertissements similaires.

Donc, ma question est: quelle est l'implication de la performance de casting / conversion en bool ? La conversion explicite a-t-elle de meilleures performances dans certaines circonstances (par exemple, pour certaines architectures ou processeurs cibles)? La conversion implicite confond-elle l'optimiseur?

L' explication de Microsoft de leur avertissement n'est pas particulièrement utile. Ils impliquent qu'il y a une bonne raison mais ils ne l'expliquent pas.




En C ++, un bool ISA int avec seulement deux valeurs 0 = false, 1 = true. Le compilateur doit seulement vérifier un bit. Pour être parfaitement clair, vrai! = 0, donc tout int peut surcharger bool, cela ne coûte que des cycles de traitement pour le faire.

En utilisant un long comme dans l'exemple de code, vous forcer beaucoup plus de contrôles de bits, ce qui causera un coup de performance.

Non ce n'est pas une optimisation prématurée, il est assez fou d'utiliser du code qui prend plus de temps de traitement à travers le tableau. C'est simplement une bonne pratique de codage.




On dirait une optimisation prématurée pour moi. Vous attendez-vous à ce que la performance de la distribution affecte sérieusement les performances de votre application? Peut-être que si vous écrivez du code noyau ou des pilotes de périphériques, mais dans la plupart des cas, tout devrait bien se passer.




L'explication de Microsoft semble être que ce qu'ils essaient de dire est:

Hey, si vous utilisez un int, mais ne stockez que des informations vraies ou fausses, faites-en un bool!

Je suis sceptique quant à ce que l'on gagnerait en performance, mais MS a peut-être constaté qu'il y avait un gain (pour leur utilisation, de toute façon). Le code de Microsoft a tendance à fonctionner énormément, alors peut-être ont-ils trouvé que la micro-optimisation valait la peine. Je crois qu'un peu de ce qui se passe dans le compilateur MS est de soutenir les choses qu'ils trouvent utiles eux-mêmes (seulement logique, non?).

Et vous vous débarrassez de quelques petits moulages sales.




long t;
bool b;
int i;
signed char c;
...

Vous obtenez un avertissement quand vous faites quelque chose qui serait "libre" si bool n'était pas nécessaire d'être 0 ou 1. b = !! t affecte effectivement le résultat de l' bool operator!(long) (langage intégré, non-overrideable) bool operator!(long)

Vous ne devriez pas attendre le! ou! = les opérateurs ne coûtent aucune instruction asm même avec un compilateur d'optimisation. Il est généralement vrai que int i = t est généralement optimisé complètement. Ou même signé char c = t; (sur x86 / amd64, si t est dans le registre% eax, après c = t, utiliser c signifie simplement utiliser% al., amd64 a un adressage par octet pour chaque registre, BTW, IIRC, dans x86 certains registres n'ont pas d'adresse octet .)

Quoi qu'il en soit, b = t; i = b ; isn't the same as c = t; i = c; it's i = !!t; instead of i = t & 0xff b = t; i = b ; isn't the same as c = t; i = c; it's i = !!t; instead of i = t & 0xff b = t; i = b ; isn't the same as c = t; i = c; it's i = !!t; instead of i = t & 0xff ;

Euh, je suppose que tout le monde sait déjà tout ça des réponses précédentes. Mon point était, l'avertissement a fait sens à moi, puisqu'il a attrapé des cas où le compilateur a dû faire des choses que vous ne lui avez pas vraiment dit, comme BOOL sur le retour parce que vous avez déclaré la fonction bool, mais renvoyez une valeur intégrale cela pourrait être vrai et! = 1. par exemple beaucoup de trucs de fenêtres retourne BOOL (int).

C'est l'un des rares avertissements de MSVC que G ++ n'a pas. Je suis beaucoup plus habitué à g ++, et cela met clairement en garde contre MSVC, mais je suis content qu'il m'en parle. J'ai écrit un fichier d'en-tête portab.h avec des stubs pour les classes / macros / fonctions MFC / Win32 que j'ai utilisées. Cela a permis à l'application MFC sur laquelle je travaille de compiler sur ma machine GNU / Linux à la maison (et avec cygwin). Je voulais principalement pouvoir compiler-tester sur quoi je travaillais à la maison, mais j'ai fini par trouver les avertissements de g ++ très utiles. C'est aussi beaucoup plus strict à propos des templates ...

Sur bool en général, je ne suis pas sûr que cela donne un meilleur code quand il est utilisé comme valeur de retour et paramètre passant. Même pour les locaux, g ++ 4.3 ne semble pas comprendre qu'il n'a pas besoin de forcer la valeur à 0 ou 1 avant de la ramifier. S'il s'agit d'une variable locale et que vous ne prenez jamais son adresse, le compilateur doit la conserver dans la taille la plus rapide. S'il doit le faire passer des registres à la pile, il peut tout aussi bien le conserver en 4 octets, car cela peut être légèrement plus rapide. (Il utilise beaucoup d'instructions movsx (signe-extension) lors du chargement / stockage de booléens (non-locaux), mais je ne me souviens pas vraiment de ce qu'il a fait pour les variables automatiques (pile locale). quantité d'espace de pile (pas un multiple de 4) dans les fonctions qui avaient des locaux de bools.)

L'utilisation des flags bool était plus lente que celle du compilateur Digital Mars D: http://www.digitalmars.com/d/archives/digitalmars/D/opEquals_needs_to_return_bool_71813.html (D ressemble beaucoup au C ++, mais abandonne complètement C compat arrière pour définir de nouvelles sémantiques sympas, et un bon support pour la métaprogrammation de template, par exemple "static if" ou "static assert" au lieu de template hacks ou de macros cpp Je voudrais vraiment essayer D un jour.

Pour les structures de données, cela peut avoir du sens, par exemple si vous voulez emballer quelques drapeaux avant un int et ensuite des doubles dans une structure, vous en aurez beaucoup.