¿Agregar `noexcept(false)` beneficia al código de alguna manera?

4 minutos de lectura

Avatar de usuario de LB--
LB–

Recientemente en mi código he estado escribiendo explícitamente noexcept(false) en funciones que sé que arrojan excepciones, principalmente para las personas que leen el código. Sin embargo, me pregunto si esto afecta el comportamiento de mi código o la forma en que el compilador lo interpreta. ¿Hace alguna diferencia?

Nota: soy consciente de que los destructores son implícitamente noexcept y que debe especificar noexcept(false) para cambiar eso, me pregunto acerca de otras funciones.

No tener un especificador de excepción y declarar explícitamente noexcept(false) son equivalentes, ver §15.4/12:

Una función sin especificación de excepción o con una especificación de excepción de la forma noexcept(constant-expression) donde la expresión constante produce false permite todas las excepciones.

Por lo tanto, el compilador no debe distinguir entre ellos al considerar las excepciones.


Más importante aún, no hay necesidad de que estés agregando noexcept(false) a sus funciones. Como desarrollador de C++, debe asumir que todas las funciones se lanzan de forma predeterminada (razón por la cual el estándar adopta esta postura), por lo que no está agregando información nueva al escribirla; es una pérdida de tiempo para todos.

Más bien, marque el caso especial donde una función definitivamente no tira con noexcepty marque los casos en los que una función mayo tirar dependiendo de alguna condición con noexcept(condition).

Si su función es intencionalmente la fuente de alguna excepción Eescríbelo en tu documentación.

  • Tenga en cuenta que en C++ 11, los destructores son por defecto noexcept(true). Si desea anular eso, tendría que agregar noexcept(false). Sin embargo, eso es casi siempre una mala idea. (Me atrevería a decir que siempre es una mala idea; solo me estoy cubriendo con “casi” en caso de que no sea lo suficientemente imaginativo). Grandes franjas de código, incluida la biblioteca estándar, asumen que los destructores siempre tienen éxito y es muy difícil de componer código de una manera recuperable si la limpieza puede fallar. En muchas situaciones, es imposible (como la inicialización estática o varios miembros de la clase).

    – Adam H. Peterson

    27 de abril de 2013 a las 0:52

  • podrías usar /* noexcept(false) */ para indicar que no ha olvidado agregar accidentalmente noexcept a la interfaz

    – PlantillaRex

    13/08/2014 a las 20:40

  • Desearía que hubiera una manera de marcar una función de tal manera que pueda lanzar incluso si el compilador puede determinar a través del análisis entre procedimientos que posiblemente no podría lanzar.

    – kchoi

    9 de septiembre de 2016 a las 0:25

  • @kchoi: si el compilador determina esto, ¿por qué es importante?

    – GManNickG

    9 sep 2016 a las 17:54

  • Depuración de sistemas integrados para errores de bus, excepciones que no son de llamada (¿las actuales tienen limitaciones?), etc.

    – kchoi

    18 de septiembre de 2016 a las 4:45

En su libro More Exceptional C++, Sutter de hierbas tiene el siguiente fragmento (págs. 130):

La respuesta correcta al Ejemplo 19-1 es mucho más simple:

// Example 19-4: The right solution
//
T::~T() /* throw() */
{
 // ... code that won't throw ...
}

El ejemplo 19-4 demuestra cómo tomar una decisión de diseño en lugar de divagar.

Tenga en cuenta que el throw() La especificación de excepción throws-nothing es solo un comentario. Ese es el estilo que he elegido seguir, en parte porque resulta que las especificaciones de excepción confieren mucho menos beneficio de lo que valen.. Si decide escribir o no la especificación es una cuestión de gusto.

(énfasis mío)

Por lo tanto, creo que debo señalar que uno de los principales expertos en código seguro de excepciones de C++ parece estar en contra del concepto general de agregar especificaciones de excepción para que las use el compilador (pero aún así dejarlo en el código para que los programadores lo entiendan) .

Solo pensé que podría ser información interesante…

  • throw() y noexcept(true) son diferentes exactamente por esta razón. lo considero vital para que los constructores de movimientos y las asignaciones de movimientos sean noexcept(true)y consideraría cualquier otra cosa como un error.

    – Pato mugido

    26 de abril de 2013 a las 21:22


  • @MooingDuck: Después de leer esto: herbsutter.com/2010/08/28/… Siento que su punto aún permanece. ¿Es tan?

    – Escualo

    26 de abril de 2013 a las 21:29

  • Aquí y Aquí el menciona que throw() es malo porque hace cosas raras. En el enlace que publicaste, parece que no tiene reservas sobre la aplicación. nothrow(true) a toda la biblioteca estándar.

    – Pato mugido

    26/04/2013 a las 21:44

¿Ha sido útil esta solución?