Especificaciones de excepciones (Throw, noexception) (C++)Exception specifications (throw, noexcept) (C++)

Las especificaciones de excepción son una característica del lenguaje C++ que indica la intención del programador sobre los tipos de excepción que se pueden propagar por una función.Exception specifications are a C++ language feature that indicate the programmer's intent about the exception types that can be propagated by a function. Puede especificar que una función pueda o no salir mediante una excepción mediante una especificación de excepción.You can specify that a function may or may not exit by an exception by using an exception specification. El compilador puede utilizar esta información para optimizar las llamadas a la función y para finalizar el programa si una excepción inesperada escapa a la función.The compiler can use this information to optimize calls to the function, and to terminate the program if an unexpected exception escapes the function.

Antes de C++ 17 había dos tipos de especificación de excepción.Prior to C++17 there were two kinds of exception specification. La especificación noexception era nueva en c++ 11.The noexcept specification was new in C++11. Especifica si el conjunto de excepciones potenciales que puede escapar la función está vacío.It specifies whether the set of potential exceptions that can escape the function is empty. La especificación de excepción dinámica, o throw(optional_type_list) especificación, quedó en desuso en c++ 11 y se quitó en c++ 17, a excepción de throw() , que es un alias para noexcept(true) .The dynamic exception specification, or throw(optional_type_list) specification, was deprecated in C++11 and removed in C++17, except for throw(), which is an alias for noexcept(true). Esta especificación de excepción se diseñó para proporcionar información de resumen sobre qué excepciones se pueden iniciar desde una función, pero en la práctica se ha descubierto que es problemática.This exception specification was designed to provide summary information about what exceptions can be thrown out of a function, but in practice it was found to be problematic. La especificación de la excepción dinámica que devolvió un poco útil era la especificación incondicional throw() .The one dynamic exception specification that did prove to be somewhat useful was the unconditional throw() specification. Por ejemplo, la declaración de función:For example, the function declaration:

void MyFunction(int i) throw();

indica al compilador que la función no produce ninguna excepción.tells the compiler that the function does not throw any exceptions. Sin embargo, en el modo /STD: c++ 14 esto podría provocar un comportamiento indefinido si la función produce una excepción.However, in /std:c++14 mode this could lead to undefined behavior if the function does throw an exception. Por lo tanto, se recomienda usar el operador noexception en lugar de uno anterior:Therefore we recommend using the noexcept operator instead of the one above:

void MyFunction(int i) noexcept;

En la tabla siguiente se resume la implementación de Microsoft C++ de especificaciones de excepciones:The following table summarizes the Microsoft C++ implementation of exception specifications:

Especificación de la excepciónException specification SignificadoMeaning
noexcept
noexcept(true)
throw()
La función no produce ninguna excepción.The function does not throw an exception. En /STD: el modo c++ 14 (que es el valor predeterminado), noexcept y noexcept(true) son equivalentes.In /std:c++14 mode (which is the default), noexcept and noexcept(true) are equivalent. Cuando se produce una excepción de una función que se declara noexcept o noexcept(true) , se invoca STD:: Terminate .When an exception is thrown from a function that is declared noexcept or noexcept(true), std::terminate is invoked. Cuando se produce una excepción desde una función declarada como throw() en el modo /STD: c++ 14 , el resultado es un comportamiento indefinido.When an exception is thrown from a function declared as throw() in /std:c++14 mode, the result is undefined behavior. No se invoca ninguna función específica.No specific function is invoked. Se trata de una divergencia con respecto al estándar de C++ 14, que requiere que el compilador invoque STD:: inesperado.This is a divergence from the C++14 standard, which required the compiler to invoke std::unexpected.
Visual Studio 2017 versión 15,5 y posteriores: en /STD: el modo c++ 17 ,, noexcept noexcept(true) y throw() son equivalentes.Visual Studio 2017 version 15.5 and later: In /std:c++17 mode , noexcept, noexcept(true), and throw() are all equivalent. En /STD: modo c++ 17 , throw() es un alias para noexcept(true) .In /std:c++17 mode, throw() is an alias for noexcept(true). En el modo /STD: c++ 17 , cuando se produce una excepción desde una función declarada con cualquiera de estas especificaciones, se invoca STD:: Terminate como requiere el estándar c++ 17.In /std:c++17 mode, when an exception is thrown from a function declared with any of these specifications, std::terminate is invoked as required by the C++17 standard.
noexcept(false)
throw(...)
Sin especificaciónNo specification
La función puede producir una excepción de cualquier tipo.The function can throw an exception of any type.
throw(type) (C++ 14 y versiones anteriores) La función puede producir una excepción de tipo type .(C++14 and earlier) The function can throw an exception of type type. El compilador acepta la sintaxis, pero lo interpreta como noexcept(false) .The compiler accepts the syntax, but interprets it as noexcept(false). En el modo /STD: c++ 17 , el compilador emite la advertencia C5040.In /std:c++17 mode the compiler issues warning C5040.

Si se usa el control de excepciones en una aplicación, debe haber una función en la pila de llamadas que controle las excepciones iniciadas antes de salir del ámbito externo de una función marcada como noexcept , noexcept(true) o throw() .If exception handling is used in an application, there must be a function in the call stack that handles thrown exceptions before they exit the outer scope of a function marked noexcept, noexcept(true), or throw(). Si alguna de las funciones llamadas entre la que produce una excepción y la que controla la excepción se especifican como noexcept , noexcept(true) (o throw() en el modo /STD: c++ 17 ), el programa se termina cuando la función noexception propaga la excepción.If any functions called between the one that throws an exception and the one that handles the exception are specified as noexcept, noexcept(true) (or throw() in /std:c++17 mode), the program is terminated when the noexcept function propagates the exception.

El comportamiento de excepción de una función depende de los siguientes factores:The exception behavior of a function depends on the following factors:

  • El modo de compilación estándar de lenguaje que se establece.Which language standard compilation mode is set.

  • Si está compilando la función con C o C++.Whether you are compiling the function under C or C++.

  • Qué opción del compilador /EH se usa.Which /EH compiler option you use.

  • Si ha especificado explícitamente la especificación de la excepción.Whether you explicitly specify the exception specification.

Las especificaciones de excepciones explícitas no se permiten en las funciones de C.Explicit exception specifications are not allowed on C functions. Se supone que una función de C produce excepciones en /EHsc y puede producir excepciones estructuradas en /EHS, /EHA o /EHac.A C function is assumed not to throw exceptions under /EHsc, and may throw structured exceptions under /EHs, /EHa, or /EHac.

En la tabla siguiente se resume si una función de C++ puede producirse potencialmente en varias opciones de control de excepciones del compilador:The following table summarizes whether a C++ function may potentially throw under various compiler exception handling options:

FunciónFunction /EHsc/EHsc /EHs/EHs /EHa/EHa /EHac/EHac
Función de C++ sin especificación de excepcionesC++ function with no exception specification Yes Yes Yes Yes
Función de C++ con la noexcept noexcept(true) especificación de excepción, o throw()C++ function with noexcept, noexcept(true), or throw() exception specification NoNo NoNo Yes Yes
Función de C++ con la noexcept(false) throw(...) especificación de excepción, o throw(type)C++ function with noexcept(false), throw(...), or throw(type) exception specification Yes Yes Yes Yes

EjemploExample

// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>

void handler() {
   printf_s("in handler\n");
}

void f1(void) throw(int) {
   printf_s("About to throw 1\n");
   if (1)
      throw 1;
}

void f5(void) throw() {
   try {
      f1();
   }
   catch(...) {
      handler();
    }
}

// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
//   f1();
// }

void __declspec(nothrow) f2(void) {
   try {
      f1();
   }
   catch(int) {
      handler();
    }
}

// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
   f1();
}

int main() {
   f2();

   try {
      f4();
   }
   catch(...) {
      printf_s("Caught exception from f4\n");
   }
   f5();
}
About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler

Consulte tambiénSee also

Instrucciones try, throw y catch (C++)try, throw, and catch Statements (C++)
Procedimientos recomendados de C++ moderno para excepciones y control de erroresModern C++ best practices for exceptions and error handling