Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Ausnahmespezifikationen sind ein C++-Sprachfeature, das die Absicht des Programmierers hinsichtlich der Ausnahmetypen angibt, die von einer Funktion weitergegeben werden können. Sie können mithilfe einer Ausnahmespezifikation angeben, ob eine Funktion durch eine Ausnahme beendet wird. Der Compiler kann diese Informationen verwenden, um Aufrufe der Funktion zu optimieren und das Programm zu beenden, wenn eine unerwartete Ausnahme die Funktion beendet.
Vor C++17 gab es zwei Arten von Ausnahmespezifikationen. Die noexcept-Spezifikation war neu in C++11. Sie gibt an, ob die Gruppe potenzieller Ausnahmen, die die Funktion beenden können, leer ist. Die dynamische Ausnahmespezifikation oderthrow(optional_type_list)
-Spezifikation wurde in C++11 veraltet und in C++17 entfernt, mit Ausnahme von throw()
, ein Alias für noexcept(true)
. Diese Ausnahmespezifikation wurde entwickelt, um zusammenfassende Informationen dazu bereitzustellen, welche Ausnahmen aus einer Funktion ausgelöst werden können. In der Praxis hat sie sich jedoch als problematisch erwiesen. Die einzige dynamische Ausnahmespezifikation, die sich als relativ nützlich erwiesen hat, war die bedingungslose throw()
-Spezifikation. Sehen Sie sich als Beispiel diese Funktionsdeklaration an:
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 des oben genannten:
void MyFunction(int i) noexcept;
In der folgenden Tabelle ist die Microsoft C++-Implementierung von Ausnahmespezifikationen zusammengefasst:
Ausnahmespezifikation | Bedeutung |
---|---|
noexcept noexcept(true) throw() |
Die Funktion löst keine Ausnahme aus. Im /std:c++14 -Modus (Standardmodus) sind noexcept und noexcept(true) äquivalent. Wenn eine Ausnahme von einer Funktion ausgelöst wird, die als noexcept oder noexcept(true) deklariert ist, wird std::terminate aufgerufen. Wenn eine Ausnahme von einer Funktion ausgelöst wird, die im /std:c++14 -Modus als throw() deklariert ist, ist das Ergebnis nicht definiertes Verhalten. Es wird keine bestimmte Funktion aufgerufen. Dies ist eine Abweichung vom C++14-Standard, der voraussetzte, dass der Compiler std::unexpected aufruft. Visual Studio 2017 Version 15.5 und höher: Im /std:c++17 -Modus sind noexcept , noexcept(true) und throw() äquivalent. Im /std:c++17 -Modus ist throw() ein Alias für noexcept(true) . Im /std:c++17 -Modus und höher wird std::terminate gemäß dem C++17-Standard aufgerufen, wenn eine Ausnahme von einer Funktion ausgelöst wird, die mit einer dieser Spezifikationen deklariert ist. |
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 als noexcept
, noexcept(true)
oder throw()
markierten Funktion beenden. Wenn Funktionen, die zwischen der Funktion, die eine Ausnahme auslöst, und der Funktion, die die Ausnahme behandelt, aufgerufen werden, als noexcept
, noexcept(true)
(bzw. im /std:c++17
-Modus als throw()
) angegeben werden, wird das Programm beendet, wenn die noexcept-Funktion die Ausnahme weitergibt.
Das Ausnahmeverhalten einer Funktion hängt von den folgenden Faktoren ab:
Dem festgelegten Standardkompilierungsmodus für die Sprache
Ob die Funktion mit C oder C++ kompiliert wird.
Der verwendeten
/EH
-CompileroptionOb die Ausnahmespezifikation explizit angegeben wird.
Explizite Ausnahmespezifikationen sind für C-Funktionen nicht zulässig. Bei einer C-Funktion wird davon ausgegangen, dass sie keine Ausnahmen unter /EHsc
und strukturierte Ausnahmen unter /EHs
, /EHa
oder /EHac
auslöst.
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 der Ausnahmespezifikation noexcept , noexcept(true) oder throw() |
No | Nein | Ja | Ja |
C++-Funktion mit der Ausnahmespezifikation noexcept(false) , throw(...) oder throw(type) |
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++)
Modernes C++: Best Practices für Ausnahmen und Fehlerbehandlung