Maison > Article > développement back-end > Pourquoi C n'utilise-t-il pas les exceptions imbriquées pour gérer les exceptions lancées par les destructeurs ?
Comprendre le problème
Lancement d'exceptions à partir de destructeurs introduit un dilemme : que faire lorsqu'une exception est déjà en cours ? L'écrasement de l'exception existante ou l'imbrication de la nouvelle exception dans celle existante sont des solutions potentielles, mais il a été décidé que terminer avec std::terminate serait l'approche standard.
Considération des exceptions imbriquées
C 11 a introduit la fonctionnalité std::nested_exception, qui pourrait potentiellement résoudre le problème en imbriquant l'ancienne exception dans la nouvelle. Cependant, cette idée n'a pas été mise en œuvre.
Raisons de la non-implémentation
Une raison pour ne pas utiliser les exceptions imbriquées dans ce contexte est le fait que std::nested_exception a utilisation très limitée, avec une seule application pratique connue : la création de piles d'appels entièrement annotées.
Cet exemple montre comment l'imbrication des exceptions fournit un moyen pratique d'ajouter du contexte et d'identifier les erreurs lors du débogage :
<code class="cpp">#include <iostream> #include <sstream> #include <exception> void rethrow(const std::string& context, ...) { std::ostringstream ss; ss << context; auto sep = " : "; (void) ((ss << sep << args), sep = ", ", 0)...); try { std::rethrow_exception(std::current_exception()); } catch(const std::invalid_argument& e) { std::throw_with_nested(std::invalid_argument(ss.str())); } catch(const std::logic_error& e) { std::throw_with_nested(std::logic_error(ss.str())); } catch(...) { std::throw_with_nested(std::runtime_error(ss.str())); } } int main() { try { outer("xyz"); outer("abcd"); } catch(std::exception& e) { print_exception(e); } return 0; } void print_exception(const std::exception& e, std::size_t depth = 0) { std::cerr << "exception: " << std::string(depth, ' ') << e.what() << '\n'; try { std::rethrow_if_nested(e); } catch (const std::exception& nested) { print_exception(nested, depth + 1); } }</code>
Résultat attendu :
exception: outer : abcd exception: inner : abcdabcd exception: really_inner exception: too long
L'exemple ci-dessus présente l'imbrication des exceptions et démontre comment cette technique aide à tracer les erreurs et à comprendre les piles d'appels.
Malgré l'utilité des exceptions imbriquées dans ce Dans un scénario spécifique, la décision de ne pas les utiliser dans le contexte des exceptions de destructeur a probablement été prise en raison de la facilité et de la fiabilité de la terminaison avec std::terminate.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!