Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between C++03 throw() specifier C++11 noexcept

Is there any difference between throw() and noexcept other than being checked at runtime and compile time, respectively?

This Wikipedia C++11 article suggests that the C++03 throw specifiers are deprecated.
Why so, is noexcept capable enough to cover all that at compile time ?

[Note: I checked this question and this article, but couldn't determine the solid reason for deprecation.]

like image 692
iammilind Avatar asked Oct 11 '12 06:10

iammilind


People also ask

What does Noexcept mean?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

What happens when Noexcept throws?

noexcept is an improved version of throw(), which is deprecated in C++11. Unlike pre-C++17 throw(), noexcept will not call std::unexpected, may or may not unwind the stack, and will call std::terminate, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().

Why should I use Noexcept?

There are two good reasons for the use of noexcept: First, an exception specifier documents the behaviour of the function. If a function is specified as noexcept, it can be safely used in a non-throwing function. Second, it is an optimisation opportunity for the compiler.

Is Noexcept faster?

Theoretically speaking, noexcept would improve performance. But it might also cause some problems on the other hand. In most of cases, it shouldn't be specified because the pros are too few to be considered and it might make your code upgrading painful.


2 Answers

Exception specifiers were deprecated because exception specifiers are generally a terrible idea. noexcept was added because it's the one reasonably useful use of an exception specifier: knowing when a function won't throw an exception. Thus it becomes a binary choice: functions that will throw and functions that won't throw.

noexcept was added rather than just removing all throw specifiers other than throw() because noexcept is more powerful. noexcept can have a parameter which compile-time resolves into a boolean. If the boolean is true, then the noexcept sticks. If the boolean is false, then the noexcept doesn't stick and the function may throw.

Thus, you can do something like this:

struct<typename T> {   void CreateOtherClass() { T t{}; } }; 

Does CreateOtherClass throw exceptions? It might, if T's default constructor can. How do we tell? Like this:

struct<typename T> {   void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; } }; 

Thus, CreateOtherClass() will throw iff the given type's default constructor throws. This fixes one of the major problems with exception specifiers: their inability to propagate up the call stack.

You can't do this with throw().

like image 151
Nicol Bolas Avatar answered Oct 11 '22 11:10

Nicol Bolas


noexcept isn't checked at compile time.

An implementation shall not reject an expression merely because when executed it throws or might throw an exception that the containing function does not allow.

When a function that is declared noexcept or throw() attempts to throw an exception the only difference is that one calls terminate and the othe calls unexpected and the latter style of exception handling has effectively been deprecated.

like image 27
CB Bailey Avatar answered Oct 11 '22 11:10

CB Bailey