55 votes

Pourquoi est-il un avertissement sur les performances sur cast pointeur vers le type bool?

S'étend.

Je pensais que j'étais en train de se refroidir quand je faisais quelque chose comme:

bool hasParent()
{
 de retour this->parentNode ;
}

Même avec un (bool) en fonte, l'avertissement n'est toujours pas aller loin.

Où this->parentNode est NULL si il n'y a pas de nœud parent.

Mais j'obtiens:

avertissement C4800: "Nœud *' : valeur forcée à la valeur booléenne "true" ou "false" (avertissement sur les performances)

Quel est le problème, yo? Pourquoi est-ce un avertissement sur les performances? J'ai pensé qu'il serait plus efficace de ne pas écrire quelque chose comme:


bool hasParent()
{
 if( this->parentNode )
 return true ;
d'autre
 return false ;
}

Mais la deuxième version, ne génère pas de mises en garde et le compilateur semble beaucoup plus heureux. Ce qui est plus rapide?

46voto

Michael Burr Points 181287

Il y a une discussion sur Microsoft Connect (http://stackoverflow.com/questions/206564/what-is-the-performance-implication-of-converting-to-bool-in-c). L'exemple donné à Microsoft:

$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp
1 bool f1 (int i)
2 {
3 return i & 2;
4 }
5
6 bool f2 (int i)
7 {
8 const bool b = i & 2;
9 return b;
10 }
11
12 bool f3 (int i)
13 {
14 const bool b = 0 != (i & 2);
15 return b;
16 }
t.cpp
t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

Et la réponse de Microsoft (par le développeur responsable de la mise en garde) est:

Cet avertissement est étonnamment utile, et a trouvé un bug dans mon code hier. Je pense que Martin est de prendre "avertissement sur les performances" hors contexte.

Il n'est pas sur le code généré, c'est de savoir si ou non le programmeur a fait part de l'intention de modifier une valeur de type int bool. Il y a une pénalité pour cela, et l'utilisateur a le choix de l'utilisation de "int" au lieu de "bool" systématiquement (ou, plus probablement, vice-versa) pour éviter le "boolifying" codegen. L'avertissement est supprimée dans le troisième cas ci-dessous, parce qu'il est clairement fait part de son intention d'accepter l'int->bool transition.

C'est un vieux avertissement, et peut avoir dépassé son but, mais c'est à se comporter comme ici conçu

Donc, fondamentalement, le développeur MS semble dire que si vous voulez "cast" un int de bool vous devriez plus correctement le faire en utilisant "return this->parentNode != 0" au lieu d'une façon implicite ou explicite de fonte.

Personnellement, je serais intéressé d'en savoir plus sur ce genre de bugs de l'avertissement découvre. Je pense que cet avertissement n'aurait pas beaucoup de valeur.

28voto

James McNellis Points 193607

Le fait que la conversion en bool ne pas faire la mise en garde en aller est voulu par la conception:

Le Casting de l'expression de type booléen ne sera pas désactiver l'avertissement, qui est par conception.

Je recommande l'approche que le MSDN description de l'avertissement C4800 recommande:

return this->parentNode != NULL;

de ce fait, il est clair que vous êtes de retour true si parentNode n'est pas un pointeur null, et false si parentNode est un pointeur null.

9voto

hirschhornsalz Points 16306

Le compilateur a besoin de générer du code supplémentaire pour la conversion d'un pointeur vers le type bool. Il s'agit d'une comparaison contre zéro et le réglage de la résultat à un si pas de zéro.

00000000004005e0 <_Z4testPv>:
bool test(void* adr) {
  4005e0:       48 85 ff                test   %rdi,%rdi
  4005e3:       0f 95 c0                setne  %al
    return adr;
}
  4005f8:       c3                      retq

Ce n'est pas directement visible à partir de la source, de sorte que le compilateur croit que c'est quelque chose que l'utilisateur doit être averti.

9voto

user9876 Points 5385

Pourquoi est-ce un avertissement sur les performances?

Le compilateur est en train de tourner ce:

bool hasParent()
{
  return this->parentNode;
}

dans:

bool hasParent()
{
  return this->parentNode != 0;
}

Cela prend environ un cycle d'horloge plus que vous pourriez vous attendre en regardant le code. C'est une insignifiante différence de performances.

Je pense que c'est mieux d'écrire l' != 0 explicitement de toute façon, car il rend le code plus clair ainsi que le silence de l'avertissement.

2voto

Loki Astari Points 116129

Il serait plus efficace d'écrire:

bool hasParent()
{
    return  this->parentNode != NULL;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X