c++ function noexcept

c++ - ¿Una función de lanzamiento teórica, pero no práctica, debería ser declarada noexceptuable?



function (5)

¿Es seguro declarar la siguiente función noexcept incluso aunque v.at(idx) teoría podría lanzar una excepción out_of_range , pero prácticamente no debido a la verificación de límites?

int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept { if (idx >= v.size()) { return -1; } return v.at(idx); }


¿A pesar de que v.at(idx) podría en teoría lanzar una excepción out_of_range , pero prácticamente no debido a la verificación de límites?

Teóricamente, no podía.

Si está pensando teóricamente acerca de esa función, entonces la verificación de límites es parte de lo que debe considerar acerca de la teoría de esa función como un todo, por lo que la única forma teórica en la que podría darse es si hubiera una condición en la cual idx >= v.size() no era cierto y, sin embargo, v.at(idx) lanzó.

Así que en tu declaración de que "podría en teoría lanzar" está mal.

(En la práctica, podría producirse, si tuvo un error en la implementación de at() en uso, pero luego tiene problemas más graves y explotar, ya que noexcept podría llevarlo a hacer, probablemente sea para mejor).


¿Cuál es su definición de "seguro"? Si lanza una excepción en una función marcada como noexcept o noexcept(true) , su programa terminará (estándar 15.4.9)

Cada vez que se lanza una excepción y la búsqueda de un manejador (15.3) encuentra el bloque más externo de una función con una especificación de excepción que no permite la excepción, entonces,

  • si la especificación de excepción es una especificación de excepción dinámica, se llama a la función std :: unexpected () (15.5.2),
  • de lo contrario, la función std :: terminate () se llama (15.5.1).

Mientras eso sea aceptable, entonces estás bien. Si no puede tolerar la terminación del programa, entonces no es seguro.


Es posible que alguien en la organización de la gran O haya hecho inteligente y haya derivado su clase de std::vector<int> y luego haya sobrecargado tanto el tamaño () como el () para lanzarlo a su gusto. Luego, en algún lugar del código se llama a su función, pero para sorpresa de todos, el programa termina en lugar de que la excepción se detecte más arriba.

De hecho, es muy poco probable, pero esto no es solo una pregunta sobre std::vector<int> ..., sino sobre la práctica de programación detrás.

Desafortunadamente, está asumiendo cosas sobre su entrada que no se pueden garantizar, y es por eso que no es seguro ; Al menos en dominios de código grande.


Es seguro. La declaración de una función noexcept resultaría en la terminación inmediata del programa (por una llamada a terminate() ) si ocurre una excepción. Mientras no se lance una excepción, todo está bien.


No tenemos el escenario completo para determinar exactamente si esa función podrá lanzar.

Aunque tus suposiciones son correctas: ya que estás haciendo lo que hace std::vector::at voluntad, es poco probable que sea perjudicial en el contexto dado. Sin embargo, en términos generales, dicha función puede estar sujeta a factores de invalidación y, por lo tanto, puede lanzar una excepción. Estos podrían ser subprocesos, procesos o señales que podrían intercalar la ejecución a un código que podría modificar std::vector , que no puede manejar eso de manera segura y tampoco std::vector::at .

Si también desea considerar esas posibilidades, necesitará algo como

int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept { try { return v.at(idx); } catch (std::out_of_range const& e) { return -1; } }