Czy jest jakaś różnica między throw()
i noexcept
innymi niż bycie sprawdzanymi odpowiednio w czasie wykonywania i kompilacji?
Ten artykuł w Wikipedii o C ++ 11 sugeruje, że specyfikatory rzutów C ++ 03 są przestarzałe.
Dlaczego tak, jest w noexcept
stanie pokryć to wszystko w czasie kompilacji?
[Uwaga: sprawdziłem to pytanie i ten artykuł , ale nie mogłem określić solidnego powodu wycofania.]
noexcept
może również powodować kontrole w czasie wykonywania. Główna różnica między nimi polega na tym, że łamanienoexcept
powoduje,std::terminate
a łamaniethrow
powodujestd::unexpected
. Również nieco inne zachowanie podczas rozwijania stosu w tych przypadkach.Odpowiedzi:
Specyfikatory wyjątków zostały wycofane, ponieważ specyfikatory wyjątków są generalnie okropnym pomysłem .
noexcept
został dodany, ponieważ jest to jedyne rozsądnie użyteczne użycie specyfikatora wyjątku: wiedza, kiedy funkcja nie zgłosi wyjątku. W ten sposób staje się wyborem binarnym: funkcje, które będą rzucać i funkcje, które nie będą rzucać.noexcept
został dodany zamiast po prostu usuwać wszystkie specyfikatory rzutów, z wyjątkiem tego,throw()
żenoexcept
jest potężniejszy.noexcept
może mieć parametr, który w czasie kompilacji zamienia się w wartość logiczną. Jeśli wartość logiczna jest prawdziwa, tonoexcept
kije. Jeśli boolean ma wartość false, tonoexcept
nie przykleja się i funkcja może rzucić.Możesz więc zrobić coś takiego:
Czy
CreateOtherClass
rzuca wyjątki? Może, jeśliT
domyślny konstruktor to potrafi. Jak powiemy? Lubię to:W ten sposób
CreateOtherClass()
zgłosi iff domyślny konstruktor danego typu. Rozwiązuje to jeden z głównych problemów ze specyfikatorami wyjątków: ich niezdolność do propagowania stosu wywołań.Nie możesz tego zrobić
throw()
.źródło
noexcept
. Nigdy nie korzystałem zethrow()
specyfikatora, nigdy i próbuję określić, czynoexcept
faktycznie zapewnia jakiekolwiek korzyści (poza dokumentacją sprawdzoną przez kompilator).std::terminate
. co jest o wiele gorzej ! kod może zakraść się do wersji, które mają zaznaczone funkcje,noexcept
a w czasie wykonywania (czyli w witrynach klientów) wykrywane są naruszenia. Chodziło mi gwarancje kompilator generuje kod, który nie rzucać wyjątków w pierwszej kolejności.throws()
to jeśli zostanie zgłoszony wyjątek, stos musi zostać odwinięty do zakresu tej funkcji (więc wszystkie automatyczne zmienne w funkcji są niszczone), w którymterminate()
to momencie jest wywoływana (przezunexpected()
). Jeśli funkcja jest zaznaczona,noexcept
to jeśli zostanie zgłoszony wyjątek, wywoływane jest zakończenie (odwinięcie stosu jest szczegółem zdefiniowanym w implementacji).noexcept
nie jest sprawdzana w czasie kompilacji.Gdy funkcja, która jest zadeklarowana
noexcept
lubthrow()
próbuje zgłosić wyjątek, jedyną różnicą jest to, że wywołaniaterminate
i inne wywołania,unexpected
a ten drugi styl obsługi wyjątków został faktycznie przestarzały.źródło
throw()
/noexcept
, sprawdzanie czasu kompilacji upewnij się, że nadpisanie również ma.std::unexpected()
jest wywoływana przez środowisko wykonawcze C ++, gdy zostanie naruszona dynamiczna specyfikacja wyjątku: wyjątek jest generowany przez funkcję, której specyfikacja wyjątku zabrania wyjątków tego typu.std::unexpected()
można również wywołać bezpośrednio z programu.W obu przypadkach
std::unexpected
wywołuje aktualnie zainstalowanystd::unexpected_handler
. Domyślnąstd::unexpected_handler
nazywastd::terminate
.źródło