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()
że noexcept
jest potężniejszy. noexcept
może mieć parametr, który w czasie kompilacji zamienia się w wartość logiczną. Jeśli wartość logiczna jest prawdziwa, to noexcept
kije. Jeśli boolean ma wartość false, to noexcept
nie przykleja się i funkcja może rzucić.
Możesz więc zrobić coś takiego:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
Czy CreateOtherClass
rzuca wyjątki? Może, jeśli T
domyślny konstruktor to potrafi. Jak powiemy? Lubię to:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
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()
.
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.