Specifikace výjimek (throw, noexcept) (C++)
Specifikace výjimek jsou funkce jazyka C++, která označuje záměr programátora o typech výjimek, které lze rozšířit funkcí. Můžete určit, že funkce může nebo nemusí ukončit výjimku pomocí specifikace výjimky. Kompilátor může tyto informace použít k optimalizaci volání funkce a k ukončení programu, pokud neočekávaná výjimka unikne funkci.
Před C++17 byly dva druhy specifikace výjimek. Specifikace noexcept byla v jazyce C++11 nová. Určuje, jestli je sada potenciálních výjimek, které mohou utéct funkci, prázdná. Specifikace dynamické výjimky nebo throw(optional_type_list)
specifikace byla v jazyce C++11 zastaralá a odebrána v jazyce C++17 s výjimkou throw()
, což je alias pro noexcept(true)
. Tato specifikace výjimky byla navržena tak, aby poskytovala souhrnné informace o výjimkách, které mohou být vyvolány z funkce, ale v praxi bylo zjištěno, že jsou problematické. Jednou dynamickou specifikací výjimek, která prokázala, že je poněkud užitečná, byla nepodmíněná throw()
specifikace. Například deklarace funkce:
void MyFunction(int i) throw();
říká kompilátoru, že funkce nevyvolá žádné výjimky. V /std:c++14
režimu to ale může vést k nedefinovanýmu chování, pokud funkce vyvolá výjimku. Proto doporučujeme místo výše uvedeného operátoru noexcept
použít:
void MyFunction(int i) noexcept;
Následující tabulka shrnuje implementaci specifikace výjimek v jazyce Microsoft C++:
Specifikace výjimek | Význam |
---|---|
noexcept noexcept(true) throw() |
Funkce nevyvolá výjimku. V /std:c++14 režimu (což je výchozí) noexcept a noexcept(true) jsou ekvivalentní. Pokud je vyvolána výjimka z funkce, která je deklarována noexcept nebo noexcept(true) , std::terminate je vyvolána. Pokud je vyvolána výjimka z funkce deklarované jako throw() v /std:c++14 režimu, výsledek je nedefinované chování. Není vyvolána žádná konkrétní funkce. Jedná se o rozdíly od standardu C++14, který vyžadoval vyvolání std::unexpected kompilátoru . Visual Studio 2017 verze 15.5 a novější: V /std:c++17 režimu , noexcept , noexcept(true) a throw() jsou všechny ekvivalentní. V /std:c++17 režimu throw() je alias pro noexcept(true) . Pokud je v /std:c++17 režimu a později vyvolána výjimka z funkce deklarované s některou z těchto specifikací, std::terminate je vyvolána podle požadavků standardu C++17. |
noexcept(false) throw(...) Bez specifikace |
Funkce může vyvolat výjimku jakéhokoli typu. |
throw(type) |
(C++14 a starší) Funkce může vyvolat výjimku typu type . Kompilátor přijímá syntaxi, ale interpretuje ji jako noexcept(false) . V /std:c++17 režimu a novějším kompilátoru zobrazí upozornění C5040. |
Pokud se v aplikaci používá zpracování výjimek, musí být v zásobníku volání funkce, která zpracovává vyvolané výjimky před ukončením vnějšího rozsahu označené noexcept
funkce , noexcept(true)
nebo throw()
. Pokud jsou některé funkce volané mezi funkcemi, které vyvolá výjimku, a funkce, která zpracovává výjimku, zadány jako noexcept
, noexcept(true)
(nebo throw()
v /std:c++17
režimu), program se ukončí, když funkce noexcept rozšíří výjimku.
Chování výjimky funkce závisí na následujících faktorech:
Který standardní režim kompilace jazyka je nastavený.
Bez ohledu na to, jestli kompilujete funkci v jazyce C nebo C++.
Kterou
/EH
možnost kompilátoru použijete.Bez ohledu na to, jestli explicitně zadáte specifikaci výjimky.
Explicitní specifikace výjimek nejsou u funkcí jazyka C povoleny. Funkce jazyka C se předpokládá, že nevyvolá výjimky v rámci /EHsc
, a může vyvolat strukturované výjimky v /EHs
oblasti , /EHa
nebo /EHac
.
Následující tabulka shrnuje, jestli může funkce jazyka C++ potenciálně vyvolat různé možnosti zpracování výjimek kompilátoru:
Function | /EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
Funkce C++ bez specifikace výjimek | Ano | Ano | Ano | Ano |
Funkce jazyka C++ se noexcept specifikací , noexcept(true) nebo throw() výjimky |
Číslo | No | Ano | Ano |
Funkce jazyka C++ se noexcept(false) specifikací , throw(...) nebo throw(type) výjimky |
Ano | Ano | Ano | Ano |
Příklad
// 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
Viz také
try
, throw
a catch
příkazy (C++)
Moderní osvědčené postupy jazyka C++ pro výjimky a zpracování chyb
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro