¿Para qué es útil noexcept?


Vi que C++ 11 agregó la palabra clave noexcept. Pero realmente no entiendo por qué es útil.

Si la función lanza cuando se supone que no debe lanzar - ¿por qué querría que el programa se bloquee?

Entonces, ¿cuándo debo usarlo?

Además, ¿cómo funcionará junto con la compilación con /Eha y el uso de _set_se_translator? Esto significa que cualquier línea de código puede lanzar una excepción de c++, porque podría lanzar una excepción SEH (debido al acceso a la memoria protegida) y se traducirá a excepción de c++.

¿Qué sucederá entonces?

Author: Moes, 2014-12-07

2 answers

El uso principal de noexcept es para algoritmos genéricos, por ejemplo, al cambiar el tamaño de un std::vector<T>: para un algoritmo eficiente mover elementos es necesario saber de antemano que ninguno de los movimientos lanzará. Si mover elementos puede lanzar, los elementos deben ser copiados en su lugar. Usando el operador noexcept(expr) la implementación de la biblioteca puede determinar si una operación en particular puede lanzar. La propiedad de operaciones que no arrojan se convierte en parte del contrato: si se viola ese contrato, todas las apuestas están fuera y puede que no haya manera de recuperar un estado válido. Rescatar antes de causar más daño es la opción natural.

Para propagar el conocimiento sobre noexcept las operaciones no arrojan también es necesario declarar funciones como tales. Con este fin, utilizarías noexcept, throw(), o noexcept(expr) con una expresión constante. El formulario que usa una expresión es necesario cuando se implementa una estructura de datos genérica: con la expresión se puede determinar si alguna de las operaciones dependientes de tipo puede lanzar una salvedad.

Por ejemplo, std::swap() se declara algo así:

template <typename T>
void swap(T& o1, T& o2) noexcept(noexcept(T(std::move(o1)) &&
                        noexcept(o1 = std::move(o2)));

Basado en noexcept(swap(a, b)) la biblioteca puede entonces elegir implementaciones eficientes diferentes de ciertas operaciones: si solo puede swap() sin arriesgar una excepción, puede violar temporalmente invariantes y recuperarlos más tarde. Si se lanza una excepción, la biblioteca puede necesitar copiar objetos en lugar de moverlos.

Es poco probable que la implementación estándar de la biblioteca C++ dependerá de muchas operaciones para ser noexcept(true). Probablemente las operaciones que verificará son principalmente aquellas involucradas en mover objetos alrededor, es decir:

  1. El destructor de una clase (tenga en cuenta que los destructores son por defecto noexcept(true) incluso sin ninguna declaración; si tiene destructor que puede lanzar, debe declararlo como tal, por ejemplo: T::~T() noexcept(false)).
  2. Los operadores de movimiento, es decir, construcción de movimiento (T::T(T&&)) y asignación de movimiento (T::operator=(T&&)).
  3. El tipo es swap() operaciones (swap(T&, T&) y posiblemente la versión miembro T::swap(T&)).

Si alguna de estas operaciones se desvía de la predeterminada, debe declararla correspondientemente para obtener la implementación más eficiente. Las versiones generadas de estas operaciones declaran si están lanzando excepciones basadas en las operaciones respectivas usadas para miembros y bases.

Aunque puedo imaginar que algunas operaciones se pueden agregar en el futuro o por algunas bibliotecas específicas, probablemente no lo haría operaciones de declaración como noexcept por ahora. Si surgen otras funciones que hacen una diferencia siendo noexcept pueden ser declaradas (y posiblemente cambiadas según sea necesario) en el futuro.

 36
Author: Dietmar Kühl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-17 11:07:42

La razón por la que el programa puede bloquearse es porque noexcept le dice al optimizador que su código no se lanzará. Si lo hace, bueno, no hay manera de predecir lo que sucederá con el código optimizado.

En cuanto a MSVC++, tendrías que comprobar qué pasa cuando implementan noexcept. Desde un punto de vista estándar, SEH es un comportamiento indefinido. Acceder a la memoria protegida ya puede bloquearse en este momento.

 4
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-07 19:21:24