Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ throw() optimization

According to Optimizing C++,

Use the empty exception specification (that is, append throw() to the declaration) for the functions you are sure will never throw exceptions.

What if I know that 90% of my methods won't throw an exception? It seems unconventional and verbose to append throw() to all of those methods. If not, what are the advantages? Or am I misunderstanding something here?

like image 786
Agrim Pathak Avatar asked Nov 06 '14 20:11

Agrim Pathak


People also ask

What is the purpose of throw in C++?

The Microsoft C++ compiler treats the throw (.) exception specifier as a promise on the part of the programmer, but there is no enforcement. It trusts you to adhere to your self-imposed contract. If an exception is thrown when the function promised that no exceptions would be thrown, the behavior is undefined.

What is throw noexcept in C++?

Exception Specifications (throw, noexcept) (C++) You can specify that a function may or may not exit by an exception by using an exception specification. The compiler can use this information to optimize calls to the function, and to terminate the program if an unexpected exception escapes the function.

What are the optimization techniques in C programming?

So, if you are learning C programming language or if you are a C language programmer, you must read these C programming optimization techniques and use all given techniques to improve your programming skills. 1) main () function should be used properly by using return type and command line arguments.

What is the throw () dynamic exception specifier in C++?

When exceptions were introduced into the C++ language, a corresponding throw (...) dynamic exception specifier was introduced which annotated which exceptions could be throw by a function. This has made a lot of people very angry and has been widely regarded as a bad move.


2 Answers

C++11 has introduced noexcept, throw is somewhat deprecated (and according to this less efficient)

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

When an empty throw specification is violated, your program is terminated; this means you should only declare your functions as non throwing, only when they have a no throw exception guarantee.

Finally you need a move constructor to be non throwing (specified with noexcept) to be able to use the r-value ref version of std::vector<T>::push_back (see a better explanation here)

like image 155
Lorah Attkins Avatar answered Sep 18 '22 17:09

Lorah Attkins


The standard throw() doesn't enhance optimizability.

If a method is marked as throw() then the compiler is forced to check if an exception is thrown from the method and unwind the stack - just like if the function is not marked as throw(). The only real difference is that for a function marked throw() the global unexpected_handler will be called (which generally calls terminate()) when the exception leaves the function, unwinding the stack to that level, instead of the behavior for functions without an exception specification which will handle the exception normally.

For pre-C++11 code, Sutter & Alexandrescu in "C++ Coding Standards" suggested:

Avoid exception specifications.

Take exception to these specifications: Don’t write exception specifications on your functions unless you’re forced to (because other code you can’t change has already introduced them; see Exceptions).

...

A common but nevertheless incorrect belief is that exception specifications statically guarantee that functions will throw only listed exceptions (possibly none), and enable compiler optimizations based on that knowledge

In fact, exception specifications actually do something slightly but fundamentally different: They cause the compiler to inject additional run-time overhead in the form of implicit try/catch blocks around the function body to enforce via run-time checking that the function does in fact emit only listed exceptions (possibly none), unless the compiler can statically prove that the exception specification can never be violated in which case it is free to optimize the checking away. And exception specifications can both enable and prevent further compiler optimizations (besides the inherent overhead already described); for example, some compilers refuse to inline functions that have exception specifications.

Note that in some versions of Microsoft's compilers (I'm not sure if this behavior has changed in more recent versions, but I don't think so), throw() is treated in a non-standard way. throw() is equivalent to __declspec(nothrow) which does allow the compiler to assume that the function will not have an exception thrown and undefined behavior will result if one is.

C++11 deprecates the C++98 style exception specification and introduced the noexcept keyword. Bjarne Stroustup's C++11 FAQ says this about it:

If a function declared noexcept throws (so that the exception tries to escape, the noexcept function) the program is terminated (by a call to terminate()). The call of terminate() cannot rely on objects being in well-defined states (i.e. there is no guarantees that destructors have been invoked, no guaranteed stack unwinding, and no possibility for resuming the program as if no problem had been encountered). This is deliberate and makes noexcept a simple, crude, and very efficient mechanism (much more efficient than the old dynamic throw() mechanism).

In C++11 if an exception is thrown from a function marked as noexcept the compiler is not obligated to unwind the stack at all. This affords some optimization possibilities. Scott Meyers discusses the new noexcept in his forthcoming book "Effective Modern C++".

like image 29
Michael Burr Avatar answered Sep 22 '22 17:09

Michael Burr