c++ - assert python
¿Cuál es la diferencia entre assert y static_assert? (5)
Sé que static_assert
hace aserciones en tiempo de compilación, y assert
- en tiempo de ejecución, pero ¿cuál es la diferencia en la práctica? Por lo que yo entiendo, en el fondo son piezas de código, como
if (condition == false) exit();
- ¿Puede alguien darme un ejemplo de dónde solo
static_assert
funcionará, o soloassert
? - ¿Hacen algo simple
if
declaración no puede hacer? - ¿Es una mala práctica usarlos?
¿Es una mala práctica usarlos?
Si se abusa, sí, particularmente assert
.
Un abuso depende de esas declaraciones de afirmación para estar activo. Nunca debe depender de assert
para hacer nada porque el código puede compilarse con NDEBUG
definido y luego assert
no hace nada. El código de producción a menudo se compila con NDEBUG
definido para garantizar que esas afirmaciones desaparezcan.
A menos que esté escribiendo un programa único que no durará más de un día o dos, no debe usar para validar la entrada del usuario. A los usuarios no les importa dónde falló el código, y el mensaje que se imprime parece un idioma extranjero para muchos usuarios. No le dice al usuario cómo corregir el error. También es muy implacable, por diseño. El mensaje emitido en respuesta a un error de entrada del usuario debe ser un mensaje que le dice al usuario cómo solucionar el problema. La mejor acción después del mensaje es ofrecer al usuario una forma de corregir el error. Si eso no se puede hacer, y si la única respuesta viable es finalizar el programa, el programa debería terminar de forma limpia. Por diseño, assert
no da como resultado un apagado limpio. Llama a abort()
lugar de exit()
.
Una consecuencia de abort()
en muchas máquinas es producir un volcado de núcleo. Un volcado de núcleo es un gran mensaje de error para un programador. Con un volcado de núcleo, un programador puede usar el depurador para ver qué salió mal en gran detalle. Una desventaja del abort()
es que las cosas no se limpian. Abort "finaliza el programa sin ejecutar destructores para objetos de duración de almacenamiento automático o estático y sin llamar a las funciones pasadas a atexit()
".
En pocas palabras: está bien (y bien) usar assert
para probar los errores de programación, pero solo en una configuración que no sea de producción. Usa algo más para probar los errores del usuario.
Hace tres preguntas, por lo que intentaré responder a cada una de ellas.
- ¿Puede alguien darme un ejemplo de dónde solo
static_assert
funcionará, o soloassert
?
static_assert
es bueno para probar la lógica en tu código en tiempo de compilación. assert
es bueno para verificar un caso durante el tiempo de ejecución que esperas que siempre tenga un resultado, pero que quizás de alguna manera podría producir un resultado inesperado en circunstancias imprevistas. Por ejemplo, solo debe usar assert
para determinar si un puntero pasado a un método es null
cuando parece que eso nunca debería ocurrir. static_assert
no captaría eso.
- ¿Hacen algo simple
if
declaración no puede hacer?
assert
se puede usar para interrumpir la ejecución del programa, por lo que podría usar if
, un mensaje de error apropiado y luego detener la ejecución del programa para obtener un efecto similar, pero assert
es un poco más simple para ese caso. static_assert
es, por supuesto, solo válido para la detección de problemas de compilación mientras que un if
debe ser programáticamente válido y no puede evaluar las mismas expectativas en tiempo de compilación. (Sin embargo, un if
se puede usar para escupir un mensaje de error en tiempo de ejecución).
- ¿Es una mala práctica usarlos?
¡De ningún modo!
OK, voy a morder:
Solo
static_assert
funciona si desea que la compilación se detenga sin éxito si se infringe una condición estática:static_assert(sizeof(void*) != 3, "Wrong machine word size");
* Solo las aserciones dinámicas pueden detectar condiciones dinámicas:assert(argc == 1);
Las sentencias simples
if
deben ser válidas y compilables; las aserciones estáticas causan fallas de compilación.No.
*) Un ejemplo práctico podría ser evitar el abuso de construcciones genéricas de plantillas, como int x; std::move<int&&>(x)
int x; std::move<int&&>(x)
.
static_assert
es una directiva de compilación. Le permite verificar la información del tipo en tiempo de compilación. Causará una falla de compilación y producirá un mensaje de error que, en la mayoría de los IDE, se capturará y se mostrará en la ventana de error del IDE.
static_assert(sizeof(int) == 4,"int should be 4 bytes");
assert
es para el tiempo de ejecución, puede verificar el valor de una variable. Si la afirmación falla, la afirmación se activará. Esto causará un cuadro de mensaje de error que aparecerá en tiempo de ejecución en algunos sistemas operativos (depende de la implementación de assert)
assert(("mypointer should never be null!", mypointer != nullptr));
static_assert
pretende hacer que la compilación falle con el mensaje especificado, mientras que la assert
tradicional está destinada a finalizar la ejecución de su programa.