Why is there a performance warning for a pointer to a bool?

Expands .

I thought I was cool when I did something like:

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

Even when using (bool), the warning still does not disappear.

If this-> parentNode is NULL if there is no parent node.

But I get:

 warning C4800: 'Node *': forcing value to bool 'true' or 'false' (performance warning)

What a deal, yo? Why is this a performance warning? I thought it would be more efficient not to write something like:

 bool hasParent ()
 {
   if (this-> parentNode)
     return true;
   else
     return false;
 }

But the second version does not generate any warnings, and the compiler seems much happier. Which is faster though?

+52
c ++ performance casting
Dec 04 '09 at 15:54
source share
7 answers

Microsoft Connect discusses this here ( What is the performance of converting to bool in C ++? ). Example provided by 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) 

And Microsoft's answer (from the developer responsible for the warning):

This warning is surprisingly useful, and yesterday found an error in my code. I think Martin takes a "performance warning" out of context.

This is not about the generated code, it is about whether the programmer signals the intention to change the value from int to bool. There is a penalty for this, and the user has the choice to use "int" instead of "bool" sequentially (or rather, vice versa) to avoid the "boolifying" codegen. The warning is suppressed in the third case below because it clearly signaled its intention to accept the int-> bool transition.

This is an old warning and may have outlived its purpose, but it behaves as described here.

So basically the MS developer seems to be saying that if you want to "dump" an int in a bool , you should use it more correctly using " return this->parentNode != 0 " instead of an implicit or explicit cast.

Personally, I would be interested to know more about what errors a warning detects. I think this warning would not be of great value.

+45
Dec 04 '09 at 16:06
source share

The fact that casting on bool does not display a design warning:

Listing an expression of type bool will not disable the warning, which is by design.

I would recommend an approach that, in the MSDN description of warning C4800, recommends:

 return this->parentNode != NULL; 

this makes it clear that you are returning true if parentNode not a null pointer and false if parentNode is a null pointer.

+25
Dec 04 '09 at 15:58
source share

The compiler must generate additional code to convert the pointer to bool. This is basically a comparison against zero and setting the result to one, if not zero.

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

This is not directly visible from the source, so the compiler believes that this is what the user should be warned about.

+8
Dec 04 '09 at 16:17
source share

Why is this a performance warning?

The compiler rotates this:

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

at

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

This takes about one beat more than you would expect from viewing the code. This is a slight performance difference.

I think itโ€™s best to write != 0 explicitly, as this makes the code more understandable and also disables the warning.

+6
Dec 04 '09 at 16:06
source share

It would be more convenient to write:

 bool hasParent() { return this->parentNode != NULL; } 
+2
Dec 04 '09 at 15:57
source share

I'm sure it depends on the compiler

+1
Dec 04 '09 at 15:58
source share

In reality, I think they will be optimized in addition, you can also try to do this:

 return this->parentNode != 0; 
0
Dec 04 '09 at 15:58
source share



All Articles