bobobobo
Esta pregunta se extiende ¿Por qué usar !! al convertir int a bool?.
Pensé que estaba siendo genial cuando hice algo como:
bool hasParent() {
return this->parentNode;
}
Dónde this->parentNode
es NULL
cuando no hay un nodo principal.
Pero estoy recibiendo:
advertencia C4800: ‘Nodo *’: valor forzado a bool ‘verdadero’ o ‘falso’ (advertencia de rendimiento)
Incluso con un lanzamiento (bool), la advertencia aún no desaparece.
¿Cuál es el trato, yo? ¿Por qué es una advertencia de rendimiento? Pensé que sería menos eficiente 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. Sin embargo, ¿cuál es más rápido?
miguel rebabas
Hay una discusión en 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 ayer encontré un error en mi código. Creo que Martin está sacando de contexto la “advertencia de desempeño”.
No se trata del código generado, se trata de si el programador ha señalado o no la intención 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 probablemente viceversa) para evitar la generación de código “boolificante”. La advertencia se suprime en el tercer caso a continuación porque indica claramente su intención de aceptar la transición int->bool.
Es una advertencia antigua 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 desea “lanzar” un int
a bool
deberías hacerlo más correctamente usando “return this->parentNode != 0
” en lugar de un molde implícito o explícito.
Personalmente, me interesaría saber más sobre qué tipo de errores descubre la advertencia. Creo que esta advertencia no tendría mucho valor.
-
Yo también creo que esta advertencia es inútil, pero nuevamente estoy sesgado contra MS VC 😉
-Gunther Piez
4 de diciembre de 2009 a las 16:24
-
Creo que debería haber un indicador del compilador para habilitar esas advertencias inútiles. Esta y las advertencias “la mayor parte de C y parte de la biblioteca estándar de C ++ están en desuso” siempre han creado una necesidad en mí simplemente de deshabilitar las advertencias cuando uso VC.
– tío Bens
4 de diciembre de 2009 a las 17:40
-
También
return this->parentNode != 0
es más propenso a errores debido a un posible error tipográficoreturn this->parentNode = 0
.– bobobobo
6 de marzo de 2010 a las 17:00
-
bobobobo: Cualquier compilador cuerdo (al menos gcc) advertirá sobre eso. Y si usa “const” correctamente, hasParent() será una función const, por lo que sería un error de compilación.
– usuario9876
20 de octubre de 2010 a las 13:04
-
existe para pasas histéricas. Algunos compiladores antiguos no conformes (probablemente VStudio v. != 0 comparación, que es un OPCODE más lento que el cast que había antes en el generador de código. Entonces, el tipo que hizo eso, también emitió una advertencia … para advertir a los clientes de mantenimiento de bases de código antiguas que algo cambió a más lento con el nuevo compilador.
– v.oddou
10 de diciembre de 2013 a las 5:27
El hecho de que lanzar a bool
no hace que la advertencia desaparezca es por diseño:
Convertir la expresión al tipo 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 claro que vas a volver true
si parentNode
no es un puntero nulo y false
si parentNode
es un puntero nulo.
-
¡Buena respuesta! Desde el punto de vista de la EM. Me gustaría expresar que no estoy de acuerdo … en mis declaraciones if, etc., nunca verifico
if( object == NULL )
por la posibilidad de teclearif( object = NULL )
y creando un error de esta manera. comprueboif( object )
yif( !object )
precisamente por eso.#pragma warning (disable:4800)
ahora escribo.– bobobobo
6 de marzo de 2010 a las 17:02
-
prefiero emitir por
!!value
. Es más corto y más genérico.– Yakov Galka
25 de noviembre de 2010 a las 9:20
-
+1 Hacer que la conversión sea explícita hace que su intención sea obvia para el próximo programador que lea el código y reconozca el costo de rendimiento de la conversión implícita.
– Adrián McCarthy
16 mayo 2012 a las 22:19
-
No responde a la pregunta: “¿Por qué hay una advertencia de rendimiento…”?
– Jon
23 de junio de 2014 a las 5:27
-
Algunos estándares de codificación sugieren cambiar los parámetros del operador alrededor del objeto NULL == para que el objeto NULL = tipográfico cause un error de compilación.
–Denise Skidmore
21 de abril de 2016 a las 20:08
Gunther piez
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 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 esto es algo sobre lo que se debe advertir al usuario.
-
No es porque esté convirtiendo un puntero en un bool, sino porque está devolviendo un bool. Este mismo código se genera si está comparando dos bools, pero usa diferentes registros según la configuración de optimización.
– Michael J. Gray
13/01/2017 a las 23:40
¿Por qué es una advertencia de rendimiento?
El compilador está convirtiendo esto:
bool hasParent()
{
return this->parentNode;
}
dentro:
bool hasParent()
{
return this->parentNode != 0;
}
Esto toma alrededor 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.
martín york
Sería más eficiente escribir:
bool hasParent()
{
return this->parentNode != NULL;
}
-
Incorrecto, el compilador generará el mismo código que el original.
– usuario9876
4 de diciembre de 2009 a las 16:02
-
user9876, ¿quién dijo que generaría un código más eficiente? Se ahorra teclear.
-Georg Fritzsche
4 de diciembre de 2009 a las 16:05
-
La parte de escritura es épsilon más eficiente. La parte ejecutora es épsilon al cuadrado más eficiente. Llamar a esto una advertencia de rendimiento es solo parte de la idiotez general sobre el rendimiento.
–Mike Dunlavey
4 de diciembre de 2009 a las 16:15
-
Quise decir en comparación con el bloque if {} else {}. Esto también elimina la advertencia.
– Martín York
4 de diciembre de 2009 a las 17:20
-
@Martin: Sé que lo hiciste. Estaba en llamas por la advertencia del compilador original. Lo siento.
–Mike Dunlavey
5 de diciembre de 2009 a las 0:50
UberJumper
Siendo realistas, creo que se optimizarían de la misma manera, también puedes intentar hacer esto:
return this->parentNode != 0;
-
Incorrecto, el compilador generará el mismo código que el original.
– usuario9876
4 de diciembre de 2009 a las 16:02
-
user9876, ¿quién dijo que generaría un código más eficiente? Se ahorra teclear.
-Georg Fritzsche
4 de diciembre de 2009 a las 16:05
-
La parte de escritura es épsilon más eficiente. La parte ejecutora es épsilon al cuadrado más eficiente. Llamar a esto una advertencia de rendimiento es solo parte de la idiotez general sobre el rendimiento.
–Mike Dunlavey
4 de diciembre de 2009 a las 16:15
-
Quise decir en comparación con el bloque if {} else {}. Esto también elimina la advertencia.
– Martín York
4 de diciembre de 2009 a las 17:20
-
@Martin: Sé que lo hiciste. Estaba en llamas por la advertencia del compilador original. Lo siento.
–Mike Dunlavey
5 de diciembre de 2009 a las 0:50
Solución alternativa: Cambiar
(expr)
a!!(expr)
– usuario2176127
07/12/2013 a las 16:40
Eso parece demasiado emocionante.
– bobobobo
7 dic 2013 a las 16:59