Ausnahmespezifikationen (Throw, noexcept) (C++)
Ausnahmespezifikationen sind ein C++-Sprachfeature, das die Absicht des Programmierers über die Ausnahmetypen angibt, die von einer Funktion weitergegeben werden können. Sie können angeben, dass eine Funktion mithilfe einer Ausnahmespezifikation eine Ausnahme verwenden kann oder nicht beendet werden kann. Der Compiler kann diese Informationen verwenden, um Aufrufe der Funktion zu optimieren und das Programm zu beenden, wenn eine unerwartete Ausnahme die Funktion ausweicht.
Vor C++17 gab es zwei Arten von Ausnahmespezifikationen. Die noexcept-Spezifikation war neu in C++11. Es gibt an, ob die Gruppe potenzieller Ausnahmen, die die Funktion escapen können, leer ist. Die dynamische Ausnahmespezifikation oder throw(optional_type_list)
-spezifikation wurde in C++11 veraltet und in C++17 entfernt, mit Ausnahme von throw()
, die ein Alias für noexcept(true)
. Diese Ausnahmespezifikation wurde entwickelt, um zusammenfassende Informationen darüber bereitzustellen, welche Ausnahmen aus einer Funktion ausgelöst werden können, aber in der Praxis wurde festgestellt, dass sie problematisch ist. Die einzige dynamische Ausnahmespezifikation, die sich als etwas nützlich erwiesen hat, war die bedingungslose throw()
Spezifikation. Beispielsweise die Funktionsdeklaration:
void MyFunction(int i) throw();
weist den Compiler an, dass die Funktion keine Ausnahmen auslöst. Im /std:c++14
Modus kann dies jedoch zu einem nicht definierten Verhalten führen, wenn die Funktion eine Ausnahme auslöst. Daher empfehlen wir die Verwendung des noexcept
Operators anstelle der oben genannten:
void MyFunction(int i) noexcept;
Die folgende Tabelle fasst die Microsoft C++-Implementierung von Ausnahmespezifikationen zusammen:
Ausnahmespezifikation | Bedeutung |
---|---|
noexcept noexcept(true) throw() |
Die Funktion löst keine Ausnahme aus. Im /std:c++14 Modus (die Standardeinstellung noexcept ) und noexcept(true) gleichwertig sind. Wenn eine Ausnahme von einer funktion ausgelöst wird, die deklariert noexcept noexcept(true) std::terminate oder aufgerufen wird. Wenn eine Ausnahme von einer als im /std:c++14 Modus deklarierten throw() Funktion ausgelöst wird, ist das Ergebnis nicht definiertes Verhalten. Es wird keine bestimmte Funktion aufgerufen. Dies ist eine Divergenz vom C++14-Standard, der zum Aufrufen std::unexpected des Compilers erforderlich ist. Visual Studio 2017, Version 15.5 und höher: Im /std:c++17 Modus , , noexcept noexcept(true) und throw() alle sind gleichwertig. Im /std:c++17 Modus throw() ist ein Alias für noexcept(true) . Im /std:c++17 Modus und später wird, wenn eine Ausnahme von einer Funktion ausgelöst wird, die mit einer dieser Spezifikationen deklariert ist, std::terminate gemäß den Anforderungen des C++17-Standards aufgerufen. |
noexcept(false) throw(...) Keine Spezifikation |
Die Funktion kann eine Ausnahme eines beliebigen Typs auslösen. |
throw(type) |
(C++14 und früher) Die Funktion kann eine Ausnahme vom Typ type auslösen. Der Compiler akzeptiert die Syntax, interpretiert sie jedoch als noexcept(false) . Im /std:c++17 Modus und höher gibt der Compiler die Warnung C5040 aus. |
Wenn die Ausnahmebehandlung in einer Anwendung verwendet wird, muss eine Funktion im Aufrufstapel vorhanden sein, die ausgelöste Ausnahmen behandelt, bevor sie den äußeren Bereich einer markierten noexcept
Funktion beenden, noexcept(true)
oder throw()
. Wenn funktionen, die zwischen dem, der eine Ausnahme auslöst, und dem Funktionen, die die Ausnahme behandeln, als , (oder throw()
im /std:c++17
Modus) angegeben noexcept
noexcept(true)
werden, wird das Programm beendet, wenn die noexcept-Funktion die Ausnahme verteilt.
Das Ausnahmeverhalten einer Funktion hängt von den folgenden Faktoren ab:
Der Standardkompilierungsmodus der Sprache wird festgelegt.
Ob die Funktion mit C oder C++ kompiliert wird.
Welche
/EH
Compileroption Sie verwenden.Ob die Ausnahmespezifikation explizit angegeben wird.
Explizite Ausnahmespezifikationen sind für C-Funktionen nicht zulässig. Es wird davon ausgegangen, dass eine C-Funktion keine Ausnahmen unterwirft/EHsc
, und sie können strukturierte Ausnahmen unter /EHs
, oder /EHa
/EHac
.
In der folgenden Tabelle wird zusammengefasst, ob eine C++-Funktion möglicherweise unter verschiedenen Compiler-Ausnahmebehandlungsoptionen ausgelöst werden kann:
Funktion | /EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
C++-Funktion ohne Ausnahmespezifikation | Ja | Ja | Ja | Ja |
C++-Funktion mit noexcept , noexcept(true) throw() oder Ausnahmespezifikation |
Nein | Nein | Ja | Ja |
C++-Funktion mit noexcept(false) , throw(...) throw(type) oder Ausnahmespezifikation |
Ja | Ja | Ja | Ja |
Beispiel
// 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
Siehe auch
try
, throw
und catch
Anweisungen (C++)
Bewährte Methoden für moderne C++-Methoden für Ausnahmen und Fehlerbehandlung
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für