From what I can tell, the SO community is divided on whether declaring a function noexcept enables meaningful compiler optimizations that would not otherwise be possible. (I'm talking specifically about compiler optimizations, not library implementation optimizations based on move_if_noexcept.) For purposes of this question, let's assume that noexcept does make meaningful code-generation optimizations possible. With that assumption, does it make sense to declare inline functions noexcept? Assuming such functions are actually inlined, this would seem to require that compilers generate the equivalent of a try block around the code resulting from the inline function at the call site, because if an exception arises in that region, terminate must be called. Without noexcept, that try block would seem to be unnecessary.
My original interest was in whether it made sense to declare Lambda functions noexcept, given that they are implicitly inline, but then I realized that the same issues arise for any inline function, not just Lambdas.
let's assume that noexcept does make meaningful code-generation optimizations possible
OK
Assuming such functions are actually inlined, this would seem to
require that compilers generate the equivalent of a try block around
the code resulting from the inline function at the call site, because
if an exception arises in that region
Not necessarily, because it might be that the compiler can look at the function body and see that it cannot possibly throw anything. Therefore the nominal exception-handling can be elided.
If the function is "fully" inlined (that is, if the inlined code contains no function calls) then I would expect that the compiler can fairly commonly make this determination -- but not for example in a case where there's a call to vector::push_back() and the writer of the function knows that sufficient space has been reserved but the compiler doesn't.
Be aware also that in a good implementation a try block might not actually require any code at all to be executed in the case where nothing is thrown.
With that assumption, does it make sense to declare inline functions noexcept?
Yes, in order to get whatever the assumed optimizations are of noexcept.
It is worth noting that there was an interesting discussion in circles of power about nothrow-related issues. I highly recommend reading these:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3227.html
http://www.stroustrup.com/N3202-noexcept.pdf
Apparently, quite influential people are interested in adding some sort of automatic nothrow deduction to C++.
After some pondering I've changed my position to almost opposite, see below
Consider this:
when you call a function that has noexcept on declaration -- you benefit from this (no need to deal with unwindability, etc)
when compiler compiles a function that has noexcept on definion -- (unless compiler can prove that function is indeed nothrow) performance suffers (now compiler needs to ensure that no exception can escape this function). You are asking it to enforce no-exceptions promise
I.e. noexcept both hurts you and benefits you. Which is not the case if function is inlined! When it is inlined -- there is no benefit from noexcept on declaration whatsoever (declaration and definition become one thing)... That is unless you are actually want compiler to enforce this for safety sake. And by safety I mean you'd rather terminate than produce wrong result.
It should be obvious now -- there is no point declaring inlined functions noexcept (keep in mind that not every inline function is gonna get inlined).
Lets have a look at different categories of functions which don't throw (you just know they don't):
non-inlined, compiler can prove it doesn't throw -- noexcept won't hurt function body (compiler will simply ignore specification) and call sites will benefit from this promise
non-inlined, compiler can't prove it doesn't throw -- noexcept will hurt function body, but benefit call sites (hard to tell what is more beneficial)
inlined, compiler can prove it doesn't throw -- noexcept serves no purpose
inlined, compiler can't prove it doesn't throw -- noexcept will hurt call site
As you see, nothrow is simply badly designed language feature. It only works if you want to enforce no-exception promise. There is no way to use it correctly -- it can give you "safety", but not performance.
noexcept keyword ended up being used both as promise (on declaration) and enforcement(on definition) -- not a perfect approach, I think (lol, second stab at exception specs and we still didn't get it right).
So, what to do?
declare your behavior (alas, language has nothing to help you here)! E.g.:
void push_back(int k); // throws only if there is no unused memory
don't put noexcept on inline functions (unless it is unlikely to be inlined, e.g. very large)
for non-inline functions (or function that is unlikely to be inlined) -- make a call. The larger function gets the smaller noexcept's negative effect becomes (comparatively) -- at some point it probably makes sense specifying it for callers' benefit
use noexcept on move constructor and move assignment operator (and destructor?). It could affects them negatively, but if you don't -- certain library functions (std::swap, some container operations) won't take the most efficient path (or won't provide the best exception guarantee). Basically any place that uses noexcept operator on your function (as of now) will force you to use noexcept specifier.
use noexcept if you don't trust calls your function makes and rather die than have it behave unexpectedly
pure virtual functions -- more often than not you don't trust people implementing these interfaces. Often it makes sense buying insurance (by specifying noexcept)
Well, how else noexcept could be designed?
I'd use two different keywords -- one for declaring a promise and another for enforcing it. E.g. noexcept and force_noexcept. In fact, enforcement isn't really required -- it can be done with try/catch + terminate() (yes, it will unwind the stack, but who cares if it is followed by std::terminate()?)
I'd force compiler to analyze all calls in given function to determine if it can throw. If it does and a noexcept promise was made -- compiler error will be emitted
For code that can throw, but you know it doesn't there should be a way to assure compiler that it is ok. Smth like this:
vector<int> v;
v.reserve(1);
...
nothrow { // memory pre-allocated, this won't throw
v.push_back(10);
}
if promise is broken (i.e. someone changed vector code and now it provides other guarantees) -- undefined behavior.
Disclaimer: this approach could be too impractical, who knows...
Related
The noexcept keyword can be appropriately applied to many function signatures, but I am unsure as to when I should consider using it in practice. Based on what I have read so far, the last-minute addition of noexcept seems to address some important issues that arise when move constructors throw. However, I am still unable to provide satisfactory answers to some practical questions that led me to read more about noexcept in the first place.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain in the neck). For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations. Do modern compilers take advantage of noexcept in this way? If not, can I expect some of them to do so in the near future?
I think it is too early to give a "best practices" answer for this as there hasn't been enough time to use it in practice. If this was asked about throw specifiers right after they came out then the answers would be very different to now.
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain).
Well, then use it when it's obvious that the function will never throw.
When can I realistically expect to observe a performance improvement after using noexcept? [...] Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations.
It seems like the biggest optimization gains are from user optimizations, not compiler ones due to the possibility of checking noexcept and overloading on it. Most compilers follow a no-penalty-if-you-don't-throw exception handling method, so I doubt it would change much (or anything) on the machine code level of your code, although perhaps reduce the binary size by removing the handling code.
Using noexcept in the big four (constructors, assignment, not destructors as they're already noexcept) will likely cause the best improvements as noexcept checks are 'common' in template code such as in std containers. For instance, std::vector won't use your class's move unless it's marked noexcept (or the compiler can deduce it otherwise).
As I keep repeating these days: semantics first.
Adding noexcept, noexcept(true) and noexcept(false) is first and foremost about semantics. It only incidentally condition a number of possible optimizations.
As a programmer reading code, the presence of noexcept is akin to that of const: it helps me better grok what may or may not happen. Therefore, it is worthwhile spending some time thinking about whether or not you know if the function will throw. For a reminder, any kind of dynamic memory allocation may throw.
Okay, now on to the possible optimizations.
The most obvious optimizations are actually performed in the libraries. C++11 provides a number of traits that allows knowing whether a function is noexcept or not, and the Standard Library implementation themselves will use those traits to favor noexcept operations on the user-defined objects they manipulate, if possible. Such as move semantics.
The compiler may only shave a bit of fat (perhaps) from the exception handling data, because it has to take into account the fact that you may have lied. If a function marked noexcept does throw, then std::terminate is called.
These semantics were chosen for two reasons:
immediately benefiting from noexcept even when dependencies do not use it already (backward compatibility)
allowing the specification of noexcept when calling functions that may theoretically throw, but are not expected to for the given arguments
This actually does make a (potentially) huge difference to the optimizer in the compiler. Compilers have actually had this feature for years via the empty throw() statement after a function definition, as well as propriety extensions. I can assure you that modern compilers do take advantage of this knowledge to generate better code.
Almost every optimization in the compiler uses something called a "flow graph" of a function to reason about what is legal. A flow graph consists of what are generally called "blocks" of the function (areas of code that have a single entrance and a single exit) and edges between the blocks to indicate where flow can jump to. Noexcept alters the flow graph.
You asked for a specific example. Consider this code:
void foo(int x) {
try {
bar();
x = 5;
// Other stuff which doesn't modify x, but might throw
} catch(...) {
// Don't modify x
}
baz(x); // Or other statement using x
}
The flow graph for this function is different if bar is labeled noexcept (there is no way for execution to jump between the end of bar and the catch statement). When labeled as noexcept, the compiler is certain the value of x is 5 during the baz function - the x=5 block is said to "dominate" the baz(x) block without the edge from bar() to the catch statement.
It can then do something called "constant propagation" to generate more efficient code. Here if baz is inlined, the statements using x might also contain constants and then what used to be a runtime evaluation can be turned into a compile-time evaluation, etc.
Anyway, the short answer: noexcept lets the compiler generate a tighter flow graph, and the flow graph is used to reason about all sorts of common compiler optimizations. To a compiler, user annotations of this nature are awesome. The compiler will try to figure this stuff out, but it usually can't (the function in question might be in another object file not visible to the compiler or transitively use some function which is not visible), or when it does, there is some trivial exception which might be thrown that you're not even aware of, so it can't implicitly label it as noexcept (allocating memory might throw bad_alloc, for example).
noexcept can dramatically improve performance of some operations. This does not happen at the level of generating machine code by the compiler, but by selecting the most effective algorithm: as others mentioned, you do this selection using function std::move_if_noexcept. For instance, the growth of std::vector (e.g., when we call reserve) must provide a strong exception-safety guarantee. If it knows that T's move constructor doesn't throw, it can just move every element. Otherwise it must copy all Ts. This has been described in detail in this post.
When can I realistically except to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Um, never? Is never a time? Never.
noexcept is for compiler performance optimizations in the same way that const is for compiler performance optimizations. That is, almost never.
noexcept is primarily used to allow "you" to detect at compile-time if a function can throw an exception. Remember: most compilers don't emit special code for exceptions unless it actually throws something. So noexcept is not a matter of giving the compiler hints about how to optimize a function so much as giving you hints about how to use a function.
Templates like move_if_noexcept will detect if the move constructor is defined with noexcept and will return a const& instead of a && of the type if it is not. It's a way of saying to move if it is very safe to do so.
In general, you should use noexcept when you think it will actually be useful to do so. Some code will take different paths if is_nothrow_constructible is true for that type. If you're using code that will do that, then feel free to noexcept appropriate constructors.
In short: use it for move constructors and similar constructs, but don't feel like you have to go nuts with it.
In Bjarne's words (The C++ Programming Language, 4th Edition, page 366):
Where termination is an acceptable response, an uncaught exception
will achieve that because it turns into a call of terminate()
(§13.5.2.5). Also, a noexcept specifier (§13.5.1.1) can make that
desire explicit.
Successful fault-tolerant systems are multilevel. Each level copes
with as many errors as it can without getting too contorted and leaves
the rest to higher levels. Exceptions support that view. Furthermore,
terminate() supports this view by providing an escape if the
exception-handling mechanism itself is corrupted or if it has been
incompletely used, thus leaving exceptions uncaught. Similarly,
noexcept provides a simple escape for errors where trying to recover
seems infeasible.
double compute(double x) noexcept; {
string s = "Courtney and Anya";
vector<double> tmp(10);
// ...
}
The vector constructor may fail to acquire memory for its ten doubles
and throw a std::bad_alloc. In that case, the program terminates. It
terminates unconditionally by invoking std::terminate() (§30.4.1.3).
It does not invoke destructors from calling functions. It is
implementation-defined whether destructors from scopes between the
throw and the noexcept (e.g., for s in compute()) are invoked. The
program is just about to terminate, so we should not depend on any
object anyway. By adding a noexcept specifier, we indicate that our
code was not written to cope with a throw.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
noexcept is tricky, as it is part of the functions interface. Especially, if you are writing a library, your client code can depend on the noexcept property. It can be difficult to change it later, as you might break existing code. That might be less of a concern when you are implementing code that is only used by your application.
If you have a function that cannot throw, ask yourself whether it will like stay noexcept or would that restrict future implementations? For example, you might want to introduce error checking of illegal arguments by throwing exceptions (e.g., for unit tests), or you might depend on other library code that could change its exception specification. In that case, it is safer to be conservative and omit noexcept.
On the other hand, if you are confident that the function should never throw and it is correct that it is part of the specification, you should declare it noexcept. However, keep in mind that the compiler will not be able to detect violations of noexcept if your implementation changes.
For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
There are four classes of functions that should you should concentrate on because they will likely have the biggest impact:
move operations (move assignment operator and move constructors)
swap operations
memory deallocators (operator delete, operator delete[])
destructors (though these are implicitly noexcept(true) unless you make them noexcept(false))
These functions should generally be noexcept, and it is most likely that library implementations can make use of the noexcept property. For example, std::vector can use non-throwing move operations without sacrificing strong exception guarantees. Otherwise, it will have to fall back to copying elements (as it did in C++98).
This kind of optimization is on the algorithmic level and does not rely on compiler optimizations. It can have a significant impact, especially if the elements are expensive to copy.
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
The advantage of noexcept against no exception specification or throw() is that the standard allows the compilers more freedom when it comes to stack unwinding. Even in the throw() case, the compiler has to completely unwind the stack (and it has to do it in the exact reverse order of the object constructions).
In the noexcept case, on the other hand, it is not required to do that. There is no requirement that the stack has to be unwound (but the compiler is still allowed to do it). That freedom allows further code optimization as it lowers the overhead of always being able to unwind the stack.
The related question about noexcept, stack unwinding and performance goes into more details about the overhead when stack unwinding is required.
I also recommend Scott Meyers book "Effective Modern C++", "Item 14: Declare functions noexcept if they won't emit exceptions" for further reading.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
When you say "I know [they] will never throw", you mean by examining the implementation of the function you know that the function will not throw. I think that approach is inside out.
It is better to consider whether a function may throw exceptions to be part of the design of the function: as important as the argument list and whether a method is a mutator (... const). Declaring that "this function never throws exceptions" is a constraint on the implementation. Omitting it does not mean the function might throw exceptions; it means that the current version of the function and all future versions may throw exceptions. It is a constraint that makes the implementation harder. But some methods must have the constraint to be practically useful; most importantly, so they can be called from destructors, but also for implementation of "roll-back" code in methods that provide the strong exception guarantee.
Here is a simple example to illustrate when it could really matter.
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(int){cout << "A(int)" << endl;}
A(const A&){cout << "A(const A&)" << endl;}
A(const A&&) noexcept {cout << "A(const A&&)" << endl;}
~A(){cout << "~S()" << endl;}
};
int main() {
vector<A> a;
cout << a.capacity() << endl;
a.emplace_back(1);
cout << a.capacity() << endl;
a.emplace_back(2);
cout << a.capacity() << endl;
return 0;
}
Here is the output
0
A(int)
1
A(int)
A(const A&&)
~S()
2
~S()
~S()
If we remove the noexcept in the move constructor, here is the output
0
A(int)
1
A(int)
A(const A&)
~S()
2
~S()
~S()
The key difference is A(const A&&) vs A(const A&&). In the second case, it has to copy all the values using the copy constructor. VERY INEFFICIENT!!
The questions is about history of C++: ISO standards, revised standards (with DR), even draft standards; all count as "a C++".
Is there any C++ where this property does not hold:
A function declared with an empty throw-specification throw() cannot throw an exception.
I'd like a counter example if that property does not hold.
Comments:
It goes without saying that throwing, then catching (without rethrowing) an exception inside a function, does that turn it info "a function throwing an exception". A function throwing an exception, according to its specification, throws at its caller. (If you do stuff internally it isn't part of the specification by definition.)
[Let's say that longjmp is forbidden as we have destructible objects.]
Others equivalent expressions of that question are:
Was there ever any case where the caller of a declared no-throw function had to worry about the possibility (equivalent properties):
of that function giving back control to its caller but not with a return statement
of seeing (and being able to catch) an exception thrown by that function
of having stack unwinding caused by the call of that function
of the caller not being non throwing if all other actions (other than calling that function) are non throwing
In other words, was there any C++ where the compiler could not optimize the calling function based on seeing a no-throw declaration of a called function?
C++17 has deprecated throw as a function annotation, mostly. It still allows throw() and considers it equivalent to noexcept(true). That means that throw() is an indication that a function is not supposed to exit because of an exception. And violating the noexcept(true) guarantee results in undefined behavior.
The semantics of throw() before C++17 were distinct and different. It used to be promised that a call to ::std::unexpected() would happen if the throw() clause was violated (i.e. an exception was thrown and resulted in the function exiting).
So, that means that before C++17 a compiler still needed to have some mechanism for detecting that a function did not exit from an exception, even if it was annotated with throw(). This is one of the reasons that the throw(...) function annotation (with stuff between the parenthesis) was deprecated because it would make no sense to have throw() to change to be equivalent to noexcept(true) without removing the other uses that the throw annotation had.
This code in compiler explorer demonstrates the 'unexpected exception' handler. If you change the standard requested to C++17, you'll see the code for that go away.
extern void a_different_function();
void test_function() throw ()
{
a_different_function();
}
In other words, was there any C++ where the compiler could not optimize the calling function based on seeing a no-throw declaration of a called function?
The answer to this direct question is no. But that alone is highly misleading.
A compiler's ability to do any kind of optimization on a a function which happens to call some other function that has a throw() declaration is extremely limited. The only real thing a compiler could do is eliminate the emission of any code dealing with exceptions in a caller function. But because of the nature of said code, it would really only be applicable if every function it calls does not throw. That's pretty much it as far as compiler optimizations of a function that calls a throw() function is concerned.
People often talk today about how noexcept enables optimizations. And that is true; judicious use of noexcept can cause code that operates on such functions to become more efficient. But it is important to remember that using noexcept does not enable compiler optimizations; it enables user-code optimizations.
Let's take the classic case of vector<T> for a T with noexcept move support. That case is not faster because the compiler sees what would otherwise be a series of copies and automatically changes them to moves just because the move constructor is noexcept. That isn't even possible for a compiler to do; it isn't allowed to rearrange your code like that, since this would be a detectable change depending on what your copy/move constructors do.
Such cases get faster because the source-code implementation of vector detects that T is nothrow-moveable. Having detected that case, it will then invoke a completely different codepath for shuffling elements of the vector around. The code calling the non-throwing function became faster because the calling code optimized itself, not because the compiler detected anything.
To put it simply, compiler optimization of the calling function was never really the point of throw() declarations.
I began adding noexcept to my code, but I'm wondering if it's even wise to bother adding it to inline functions. I'm assuming the optimizer would omit the runtime check when it's clearly unneeded... but from a human/style perspective, is it worth adding noexcept to trivial functions like getters, settings, increment functions, etc? I'm thinking it's visual clutter for something totally obvious. I'm debating a rule that inline functions get to omit noexcept, but normal .hpp/.cpp functions have to have it if they don't throw.
Secondly, I have a large amount of code that can't throw at all because it has no allocations (in my chess engine), that includes no STL or anything else that might fail, so success is always guaranteed. Wouldn't noexcept slow it down due to the runtime check? Does anyone use a macro to switch between using noexcept for DEBUG builds, but swap to throw() for release, which is compile-time only?
If your inline function is a leaf-level function, i.e. It calls no functions itself, then in theory a compiler could determine that it won't throw and omit whatever exception handling may have been generated otherwise. So performance-wise, it may prove unnecessary.
Having said that, you shouldn't expect to see a performance reduction from adding noexcept. Whatever code that would have to have been generated to handle propagation of exceptions shouldn't become any more complicated by adding noexcept. It's worth noting that a compiler is permitted to omit unwinding the stack entirely if an exception is thrown from a noexcept function. This is largely where the direct benefits of noexcept come from.
As for a style recommendation, first and foremost, consider whether noexcept would be a useful part of your interface. Things such as move operations can benefit greatly from being noexcept for algorithmic reasons, but besides those, it's really up to you to decide where noexcept has value for you, your interface and the users of your interface.
If this doesn't answer your question, feel free to comment on my answer and I will clarify further.
Sidenote: throw(), as well being deprecated in C++11, doesn't give the same guarantees as noexcept. If an exception is thrown through a function declared throw(), the stack must be completely unwound up to the caller of that function. See 15.5.2.1 in version N3337 of the C++ standard for reference to this behaviour.
By adding noexcept or noexcept(true) specifier to function, you ask compiler to add run-time check and call std::terminate. So you have a small performance hit. You should gain something from it or I can see no sence otherwise. Standard library has traits:
is_nothrow_constructible,
is_nothrow_default_constructible,
is_nothrow_move_constructible,
is_nothrow_copy_constructible,
is_nothrow_assignable,
is_nothrow_move_assignable,
is_nothrow_copy_assignable,
is_nothrow_destructible.
Containers in standard library is known to use these traits on contained types to perform optimization (move instead of copy). Maybe some other optimizations, I don't know about. This make sense for me to add noexcept specifier to appropriate constructor or assignment operator (of course if they really don't throw), that these traits will return true, and get performance boost, when using your class with standard containers.
I don't think that adding noexcept to ordinary function like getter or setter is a good idea: you get performance hit and gain nothing.
If your code doesn't throw and doesn't use standard library - my advice: do not use noexcept at all.
The noexcept keyword can be appropriately applied to many function signatures, but I am unsure as to when I should consider using it in practice. Based on what I have read so far, the last-minute addition of noexcept seems to address some important issues that arise when move constructors throw. However, I am still unable to provide satisfactory answers to some practical questions that led me to read more about noexcept in the first place.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain in the neck). For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations. Do modern compilers take advantage of noexcept in this way? If not, can I expect some of them to do so in the near future?
I think it is too early to give a "best practices" answer for this as there hasn't been enough time to use it in practice. If this was asked about throw specifiers right after they came out then the answers would be very different to now.
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain).
Well, then use it when it's obvious that the function will never throw.
When can I realistically expect to observe a performance improvement after using noexcept? [...] Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations.
It seems like the biggest optimization gains are from user optimizations, not compiler ones due to the possibility of checking noexcept and overloading on it. Most compilers follow a no-penalty-if-you-don't-throw exception handling method, so I doubt it would change much (or anything) on the machine code level of your code, although perhaps reduce the binary size by removing the handling code.
Using noexcept in the big four (constructors, assignment, not destructors as they're already noexcept) will likely cause the best improvements as noexcept checks are 'common' in template code such as in std containers. For instance, std::vector won't use your class's move unless it's marked noexcept (or the compiler can deduce it otherwise).
As I keep repeating these days: semantics first.
Adding noexcept, noexcept(true) and noexcept(false) is first and foremost about semantics. It only incidentally condition a number of possible optimizations.
As a programmer reading code, the presence of noexcept is akin to that of const: it helps me better grok what may or may not happen. Therefore, it is worthwhile spending some time thinking about whether or not you know if the function will throw. For a reminder, any kind of dynamic memory allocation may throw.
Okay, now on to the possible optimizations.
The most obvious optimizations are actually performed in the libraries. C++11 provides a number of traits that allows knowing whether a function is noexcept or not, and the Standard Library implementation themselves will use those traits to favor noexcept operations on the user-defined objects they manipulate, if possible. Such as move semantics.
The compiler may only shave a bit of fat (perhaps) from the exception handling data, because it has to take into account the fact that you may have lied. If a function marked noexcept does throw, then std::terminate is called.
These semantics were chosen for two reasons:
immediately benefiting from noexcept even when dependencies do not use it already (backward compatibility)
allowing the specification of noexcept when calling functions that may theoretically throw, but are not expected to for the given arguments
This actually does make a (potentially) huge difference to the optimizer in the compiler. Compilers have actually had this feature for years via the empty throw() statement after a function definition, as well as propriety extensions. I can assure you that modern compilers do take advantage of this knowledge to generate better code.
Almost every optimization in the compiler uses something called a "flow graph" of a function to reason about what is legal. A flow graph consists of what are generally called "blocks" of the function (areas of code that have a single entrance and a single exit) and edges between the blocks to indicate where flow can jump to. Noexcept alters the flow graph.
You asked for a specific example. Consider this code:
void foo(int x) {
try {
bar();
x = 5;
// Other stuff which doesn't modify x, but might throw
} catch(...) {
// Don't modify x
}
baz(x); // Or other statement using x
}
The flow graph for this function is different if bar is labeled noexcept (there is no way for execution to jump between the end of bar and the catch statement). When labeled as noexcept, the compiler is certain the value of x is 5 during the baz function - the x=5 block is said to "dominate" the baz(x) block without the edge from bar() to the catch statement.
It can then do something called "constant propagation" to generate more efficient code. Here if baz is inlined, the statements using x might also contain constants and then what used to be a runtime evaluation can be turned into a compile-time evaluation, etc.
Anyway, the short answer: noexcept lets the compiler generate a tighter flow graph, and the flow graph is used to reason about all sorts of common compiler optimizations. To a compiler, user annotations of this nature are awesome. The compiler will try to figure this stuff out, but it usually can't (the function in question might be in another object file not visible to the compiler or transitively use some function which is not visible), or when it does, there is some trivial exception which might be thrown that you're not even aware of, so it can't implicitly label it as noexcept (allocating memory might throw bad_alloc, for example).
noexcept can dramatically improve performance of some operations. This does not happen at the level of generating machine code by the compiler, but by selecting the most effective algorithm: as others mentioned, you do this selection using function std::move_if_noexcept. For instance, the growth of std::vector (e.g., when we call reserve) must provide a strong exception-safety guarantee. If it knows that T's move constructor doesn't throw, it can just move every element. Otherwise it must copy all Ts. This has been described in detail in this post.
When can I realistically except to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Um, never? Is never a time? Never.
noexcept is for compiler performance optimizations in the same way that const is for compiler performance optimizations. That is, almost never.
noexcept is primarily used to allow "you" to detect at compile-time if a function can throw an exception. Remember: most compilers don't emit special code for exceptions unless it actually throws something. So noexcept is not a matter of giving the compiler hints about how to optimize a function so much as giving you hints about how to use a function.
Templates like move_if_noexcept will detect if the move constructor is defined with noexcept and will return a const& instead of a && of the type if it is not. It's a way of saying to move if it is very safe to do so.
In general, you should use noexcept when you think it will actually be useful to do so. Some code will take different paths if is_nothrow_constructible is true for that type. If you're using code that will do that, then feel free to noexcept appropriate constructors.
In short: use it for move constructors and similar constructs, but don't feel like you have to go nuts with it.
In Bjarne's words (The C++ Programming Language, 4th Edition, page 366):
Where termination is an acceptable response, an uncaught exception
will achieve that because it turns into a call of terminate()
(§13.5.2.5). Also, a noexcept specifier (§13.5.1.1) can make that
desire explicit.
Successful fault-tolerant systems are multilevel. Each level copes
with as many errors as it can without getting too contorted and leaves
the rest to higher levels. Exceptions support that view. Furthermore,
terminate() supports this view by providing an escape if the
exception-handling mechanism itself is corrupted or if it has been
incompletely used, thus leaving exceptions uncaught. Similarly,
noexcept provides a simple escape for errors where trying to recover
seems infeasible.
double compute(double x) noexcept; {
string s = "Courtney and Anya";
vector<double> tmp(10);
// ...
}
The vector constructor may fail to acquire memory for its ten doubles
and throw a std::bad_alloc. In that case, the program terminates. It
terminates unconditionally by invoking std::terminate() (§30.4.1.3).
It does not invoke destructors from calling functions. It is
implementation-defined whether destructors from scopes between the
throw and the noexcept (e.g., for s in compute()) are invoked. The
program is just about to terminate, so we should not depend on any
object anyway. By adding a noexcept specifier, we indicate that our
code was not written to cope with a throw.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
noexcept is tricky, as it is part of the functions interface. Especially, if you are writing a library, your client code can depend on the noexcept property. It can be difficult to change it later, as you might break existing code. That might be less of a concern when you are implementing code that is only used by your application.
If you have a function that cannot throw, ask yourself whether it will like stay noexcept or would that restrict future implementations? For example, you might want to introduce error checking of illegal arguments by throwing exceptions (e.g., for unit tests), or you might depend on other library code that could change its exception specification. In that case, it is safer to be conservative and omit noexcept.
On the other hand, if you are confident that the function should never throw and it is correct that it is part of the specification, you should declare it noexcept. However, keep in mind that the compiler will not be able to detect violations of noexcept if your implementation changes.
For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
There are four classes of functions that should you should concentrate on because they will likely have the biggest impact:
move operations (move assignment operator and move constructors)
swap operations
memory deallocators (operator delete, operator delete[])
destructors (though these are implicitly noexcept(true) unless you make them noexcept(false))
These functions should generally be noexcept, and it is most likely that library implementations can make use of the noexcept property. For example, std::vector can use non-throwing move operations without sacrificing strong exception guarantees. Otherwise, it will have to fall back to copying elements (as it did in C++98).
This kind of optimization is on the algorithmic level and does not rely on compiler optimizations. It can have a significant impact, especially if the elements are expensive to copy.
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
The advantage of noexcept against no exception specification or throw() is that the standard allows the compilers more freedom when it comes to stack unwinding. Even in the throw() case, the compiler has to completely unwind the stack (and it has to do it in the exact reverse order of the object constructions).
In the noexcept case, on the other hand, it is not required to do that. There is no requirement that the stack has to be unwound (but the compiler is still allowed to do it). That freedom allows further code optimization as it lowers the overhead of always being able to unwind the stack.
The related question about noexcept, stack unwinding and performance goes into more details about the overhead when stack unwinding is required.
I also recommend Scott Meyers book "Effective Modern C++", "Item 14: Declare functions noexcept if they won't emit exceptions" for further reading.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
When you say "I know [they] will never throw", you mean by examining the implementation of the function you know that the function will not throw. I think that approach is inside out.
It is better to consider whether a function may throw exceptions to be part of the design of the function: as important as the argument list and whether a method is a mutator (... const). Declaring that "this function never throws exceptions" is a constraint on the implementation. Omitting it does not mean the function might throw exceptions; it means that the current version of the function and all future versions may throw exceptions. It is a constraint that makes the implementation harder. But some methods must have the constraint to be practically useful; most importantly, so they can be called from destructors, but also for implementation of "roll-back" code in methods that provide the strong exception guarantee.
Here is a simple example to illustrate when it could really matter.
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(int){cout << "A(int)" << endl;}
A(const A&){cout << "A(const A&)" << endl;}
A(const A&&) noexcept {cout << "A(const A&&)" << endl;}
~A(){cout << "~S()" << endl;}
};
int main() {
vector<A> a;
cout << a.capacity() << endl;
a.emplace_back(1);
cout << a.capacity() << endl;
a.emplace_back(2);
cout << a.capacity() << endl;
return 0;
}
Here is the output
0
A(int)
1
A(int)
A(const A&&)
~S()
2
~S()
~S()
If we remove the noexcept in the move constructor, here is the output
0
A(int)
1
A(int)
A(const A&)
~S()
2
~S()
~S()
The key difference is A(const A&&) vs A(const A&&). In the second case, it has to copy all the values using the copy constructor. VERY INEFFICIENT!!
The noexcept keyword can be appropriately applied to many function signatures, but I am unsure as to when I should consider using it in practice. Based on what I have read so far, the last-minute addition of noexcept seems to address some important issues that arise when move constructors throw. However, I am still unable to provide satisfactory answers to some practical questions that led me to read more about noexcept in the first place.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain in the neck). For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations. Do modern compilers take advantage of noexcept in this way? If not, can I expect some of them to do so in the near future?
I think it is too early to give a "best practices" answer for this as there hasn't been enough time to use it in practice. If this was asked about throw specifiers right after they came out then the answers would be very different to now.
Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain).
Well, then use it when it's obvious that the function will never throw.
When can I realistically expect to observe a performance improvement after using noexcept? [...] Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations.
It seems like the biggest optimization gains are from user optimizations, not compiler ones due to the possibility of checking noexcept and overloading on it. Most compilers follow a no-penalty-if-you-don't-throw exception handling method, so I doubt it would change much (or anything) on the machine code level of your code, although perhaps reduce the binary size by removing the handling code.
Using noexcept in the big four (constructors, assignment, not destructors as they're already noexcept) will likely cause the best improvements as noexcept checks are 'common' in template code such as in std containers. For instance, std::vector won't use your class's move unless it's marked noexcept (or the compiler can deduce it otherwise).
As I keep repeating these days: semantics first.
Adding noexcept, noexcept(true) and noexcept(false) is first and foremost about semantics. It only incidentally condition a number of possible optimizations.
As a programmer reading code, the presence of noexcept is akin to that of const: it helps me better grok what may or may not happen. Therefore, it is worthwhile spending some time thinking about whether or not you know if the function will throw. For a reminder, any kind of dynamic memory allocation may throw.
Okay, now on to the possible optimizations.
The most obvious optimizations are actually performed in the libraries. C++11 provides a number of traits that allows knowing whether a function is noexcept or not, and the Standard Library implementation themselves will use those traits to favor noexcept operations on the user-defined objects they manipulate, if possible. Such as move semantics.
The compiler may only shave a bit of fat (perhaps) from the exception handling data, because it has to take into account the fact that you may have lied. If a function marked noexcept does throw, then std::terminate is called.
These semantics were chosen for two reasons:
immediately benefiting from noexcept even when dependencies do not use it already (backward compatibility)
allowing the specification of noexcept when calling functions that may theoretically throw, but are not expected to for the given arguments
This actually does make a (potentially) huge difference to the optimizer in the compiler. Compilers have actually had this feature for years via the empty throw() statement after a function definition, as well as propriety extensions. I can assure you that modern compilers do take advantage of this knowledge to generate better code.
Almost every optimization in the compiler uses something called a "flow graph" of a function to reason about what is legal. A flow graph consists of what are generally called "blocks" of the function (areas of code that have a single entrance and a single exit) and edges between the blocks to indicate where flow can jump to. Noexcept alters the flow graph.
You asked for a specific example. Consider this code:
void foo(int x) {
try {
bar();
x = 5;
// Other stuff which doesn't modify x, but might throw
} catch(...) {
// Don't modify x
}
baz(x); // Or other statement using x
}
The flow graph for this function is different if bar is labeled noexcept (there is no way for execution to jump between the end of bar and the catch statement). When labeled as noexcept, the compiler is certain the value of x is 5 during the baz function - the x=5 block is said to "dominate" the baz(x) block without the edge from bar() to the catch statement.
It can then do something called "constant propagation" to generate more efficient code. Here if baz is inlined, the statements using x might also contain constants and then what used to be a runtime evaluation can be turned into a compile-time evaluation, etc.
Anyway, the short answer: noexcept lets the compiler generate a tighter flow graph, and the flow graph is used to reason about all sorts of common compiler optimizations. To a compiler, user annotations of this nature are awesome. The compiler will try to figure this stuff out, but it usually can't (the function in question might be in another object file not visible to the compiler or transitively use some function which is not visible), or when it does, there is some trivial exception which might be thrown that you're not even aware of, so it can't implicitly label it as noexcept (allocating memory might throw bad_alloc, for example).
noexcept can dramatically improve performance of some operations. This does not happen at the level of generating machine code by the compiler, but by selecting the most effective algorithm: as others mentioned, you do this selection using function std::move_if_noexcept. For instance, the growth of std::vector (e.g., when we call reserve) must provide a strong exception-safety guarantee. If it knows that T's move constructor doesn't throw, it can just move every element. Otherwise it must copy all Ts. This has been described in detail in this post.
When can I realistically except to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
Um, never? Is never a time? Never.
noexcept is for compiler performance optimizations in the same way that const is for compiler performance optimizations. That is, almost never.
noexcept is primarily used to allow "you" to detect at compile-time if a function can throw an exception. Remember: most compilers don't emit special code for exceptions unless it actually throws something. So noexcept is not a matter of giving the compiler hints about how to optimize a function so much as giving you hints about how to use a function.
Templates like move_if_noexcept will detect if the move constructor is defined with noexcept and will return a const& instead of a && of the type if it is not. It's a way of saying to move if it is very safe to do so.
In general, you should use noexcept when you think it will actually be useful to do so. Some code will take different paths if is_nothrow_constructible is true for that type. If you're using code that will do that, then feel free to noexcept appropriate constructors.
In short: use it for move constructors and similar constructs, but don't feel like you have to go nuts with it.
In Bjarne's words (The C++ Programming Language, 4th Edition, page 366):
Where termination is an acceptable response, an uncaught exception
will achieve that because it turns into a call of terminate()
(§13.5.2.5). Also, a noexcept specifier (§13.5.1.1) can make that
desire explicit.
Successful fault-tolerant systems are multilevel. Each level copes
with as many errors as it can without getting too contorted and leaves
the rest to higher levels. Exceptions support that view. Furthermore,
terminate() supports this view by providing an escape if the
exception-handling mechanism itself is corrupted or if it has been
incompletely used, thus leaving exceptions uncaught. Similarly,
noexcept provides a simple escape for errors where trying to recover
seems infeasible.
double compute(double x) noexcept; {
string s = "Courtney and Anya";
vector<double> tmp(10);
// ...
}
The vector constructor may fail to acquire memory for its ten doubles
and throw a std::bad_alloc. In that case, the program terminates. It
terminates unconditionally by invoking std::terminate() (§30.4.1.3).
It does not invoke destructors from calling functions. It is
implementation-defined whether destructors from scopes between the
throw and the noexcept (e.g., for s in compute()) are invoked. The
program is just about to terminate, so we should not depend on any
object anyway. By adding a noexcept specifier, we indicate that our
code was not written to cope with a throw.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
noexcept is tricky, as it is part of the functions interface. Especially, if you are writing a library, your client code can depend on the noexcept property. It can be difficult to change it later, as you might break existing code. That might be less of a concern when you are implementing code that is only used by your application.
If you have a function that cannot throw, ask yourself whether it will like stay noexcept or would that restrict future implementations? For example, you might want to introduce error checking of illegal arguments by throwing exceptions (e.g., for unit tests), or you might depend on other library code that could change its exception specification. In that case, it is safer to be conservative and omit noexcept.
On the other hand, if you are confident that the function should never throw and it is correct that it is part of the specification, you should declare it noexcept. However, keep in mind that the compiler will not be able to detect violations of noexcept if your implementation changes.
For which situations should I be more careful about the use of noexcept, and for which situations can I get away with the implied noexcept(false)?
There are four classes of functions that should you should concentrate on because they will likely have the biggest impact:
move operations (move assignment operator and move constructors)
swap operations
memory deallocators (operator delete, operator delete[])
destructors (though these are implicitly noexcept(true) unless you make them noexcept(false))
These functions should generally be noexcept, and it is most likely that library implementations can make use of the noexcept property. For example, std::vector can use non-throwing move operations without sacrificing strong exception guarantees. Otherwise, it will have to fall back to copying elements (as it did in C++98).
This kind of optimization is on the algorithmic level and does not rely on compiler optimizations. It can have a significant impact, especially if the elements are expensive to copy.
When can I realistically expect to observe a performance improvement after using noexcept? In particular, give an example of code for which a C++ compiler is able to generate better machine code after the addition of noexcept.
The advantage of noexcept against no exception specification or throw() is that the standard allows the compilers more freedom when it comes to stack unwinding. Even in the throw() case, the compiler has to completely unwind the stack (and it has to do it in the exact reverse order of the object constructions).
In the noexcept case, on the other hand, it is not required to do that. There is no requirement that the stack has to be unwound (but the compiler is still allowed to do it). That freedom allows further code optimization as it lowers the overhead of always being able to unwind the stack.
The related question about noexcept, stack unwinding and performance goes into more details about the overhead when stack unwinding is required.
I also recommend Scott Meyers book "Effective Modern C++", "Item 14: Declare functions noexcept if they won't emit exceptions" for further reading.
There are many examples of functions that I know will never throw, but for which the compiler cannot determine so on its own. Should I append noexcept to the function declaration in all such cases?
When you say "I know [they] will never throw", you mean by examining the implementation of the function you know that the function will not throw. I think that approach is inside out.
It is better to consider whether a function may throw exceptions to be part of the design of the function: as important as the argument list and whether a method is a mutator (... const). Declaring that "this function never throws exceptions" is a constraint on the implementation. Omitting it does not mean the function might throw exceptions; it means that the current version of the function and all future versions may throw exceptions. It is a constraint that makes the implementation harder. But some methods must have the constraint to be practically useful; most importantly, so they can be called from destructors, but also for implementation of "roll-back" code in methods that provide the strong exception guarantee.
Here is a simple example to illustrate when it could really matter.
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(int){cout << "A(int)" << endl;}
A(const A&){cout << "A(const A&)" << endl;}
A(const A&&) noexcept {cout << "A(const A&&)" << endl;}
~A(){cout << "~S()" << endl;}
};
int main() {
vector<A> a;
cout << a.capacity() << endl;
a.emplace_back(1);
cout << a.capacity() << endl;
a.emplace_back(2);
cout << a.capacity() << endl;
return 0;
}
Here is the output
0
A(int)
1
A(int)
A(const A&&)
~S()
2
~S()
~S()
If we remove the noexcept in the move constructor, here is the output
0
A(int)
1
A(int)
A(const A&)
~S()
2
~S()
~S()
The key difference is A(const A&&) vs A(const A&&). In the second case, it has to copy all the values using the copy constructor. VERY INEFFICIENT!!