c++ - programacion - metodo bool en c
¿Por qué hay una advertencia de rendimiento en el puntero de molde para bool? (7)
Extends .
Pensé que estaba siendo genial cuando hice algo como:
bool hasParent() { return this->parentNode ; }
Incluso con un yeso (bool), la advertencia aún no desaparece.
Donde this-> parentNode es NULL cuando no hay un nodo padre.
Pero estoy obteniendo:
warning C4800: ''Node *'' : forcing value to bool ''true'' or ''false'' (performance warning)
¿Cuál es el problema, yo? ¿Por qué es eso una advertencia de rendimiento? Pensé que sería más eficiente no escribir algo como:
bool hasParent() { if( this->parentNode ) return true ; else return false ; }
Pero la segunda versión no genera advertencias y el compilador parece mucho más feliz. ¿Cuál es más rápido?
¿Por qué es eso una advertencia de rendimiento?
El compilador está convirtiendo esto:
bool hasParent()
{
return this->parentNode;
}
dentro:
bool hasParent()
{
return this->parentNode != 0;
}
Esto lleva aproximadamente un ciclo de reloj más de lo que cabría esperar al mirar el código. Es una diferencia de rendimiento insignificante.
Creo que es mejor escribir el != 0
explícitamente de todos modos, ya que hace que el código sea más claro y silencia la advertencia.
El compilador necesita generar código adicional para convertir un puntero a bool. Básicamente es una comparación contra cero y establecer el resultado en uno si no en cero.
00000000004005e0 <_Z4testPv>:
bool test(void* adr) {
4005e0: 48 85 ff test %rdi,%rdi
4005e3: 0f 95 c0 setne %al
return adr;
}
4005f8: c3 retq
Esto no es directamente visible desde la fuente, por lo que el compilador cree que es algo que debe advertirse al usuario.
El hecho de que el lanzamiento de bool
no hace que la advertencia desaparezca es por diseño :
Lanzar la expresión para escribir bool no deshabilitará la advertencia, que es por diseño.
Recomendaría el enfoque que recomienda la descripción de MSDN de la advertencia C4800:
return this->parentNode != NULL;
esto deja en claro que está regresando true
si parentNode
no es un puntero nulo y false
si parentNode
es un puntero nulo.
Estoy bastante seguro de que esto depende del compilador
Hay una discusión sobre Microsoft Connect sobre esto ( ¿Cuál es la implicación de rendimiento de convertir a bool en C ++? ). El ejemplo dado a Microsoft es:
$ 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)
Y la respuesta de Microsoft (del desarrollador responsable de la advertencia) es:
Esta advertencia es sorprendentemente útil y descubrí un error en mi código ayer. Creo que Martin está tomando "advertencia de rendimiento" fuera de contexto.
No se trata del código generado, sino de si el programador ha indicado o no el intento de cambiar un valor de int a bool. Hay una penalización por eso, y el usuario tiene la opción de usar "int" en lugar de "bool" de manera consistente (o más bien viceversa) para evitar el codegen "boolifying". La advertencia se suprime en el tercer caso a continuación porque claramente ha indicado su intención de aceptar la transición int-> bool.
Es una vieja advertencia, y puede haber sobrevivido a su propósito, pero se está comportando como se diseñó aquí.
Así que, básicamente, el desarrollador de MS parece estar diciendo que si quieres ''lanzar'' un int
a bool
deberías hacerlo más apropiadamente usando " return this->parentNode != 0
" en lugar de un elenco implícito o explícito.
Personalmente, me gustaría saber más sobre qué tipo de errores descubre la advertencia. Pensaría que esta advertencia no tendría mucho valor.
Sería más eficiente escribir:
bool hasParent()
{
return this->parentNode != NULL;
}
Siendo realistas, creo que optimizarían lo mismo, también puedes intentar hacer esto:
return this->parentNode != 0;