Hello again! In this video, we are going to look at the noexcept keyword.
This came in, in C++11.
It replaces the older throw() with an empty exception list.
We can declare a function as noexcept and that means that the function does not throw exceptions.
Or at least it is not supposed to.
So this is the new version of writing throw() with an empty exception list.
If an exception is thrown, then the program terminates immediately.
Noexcept is a promise to callers of this function that it is not going to throw any exceptions.
So a noexcept function provides the "no throw" guarantee.
And that is helpful to us if we are writing exception-safe codes and we want to call that function.
noexcept also has performance advantages.
It helps the compiler generate better-optimized code.
It gives the compiler more information about what the code might or might not do.
So the compiler might be able to make some extra assumptions, which save time.
And it also means that the compiler does not neede to generate code for stack unwinding for that
function.
In modern C++, we have optimized versions of some operators, which are not necessarily exception-safe.
We will talk about this when we cover move semantics.
The standard library will only use these operators if they are declared noexcept. Otherwise it is going
to be cautious and call the older versions, which are not optimized but safer.
So if you do not declare things as noexcept, you may lose out on these optimized operators.
So when should we use
noexcept?
And the answer is, wherever possible. If we are certain that a function is not going to throw any
exceptions, or not call functions, which might have exceptions. It is also useful if we could get
an exception, but there is nothing useful we could do.
And the safest thing to do is to shut down the program, before anything else goes wrong.
So that is another situation where noexcept is useful.
So, some examples where we could use noexcept are: overloading the standard swap() function, and for class destructors.
We cannot overload on being noexcept: a function can only be one or the other.
You cannot have two different versions.
noexcept is part of the function's type, but it is not part of the function's signature.
So that is similar reasoning to the return type.
You cannot overdo it on return value in C++, either.
With class hierarchies, the property of being noexcept is inherited.
So if you have a virtual function in the base class, which is noexcept, then all the overrides in derived
classes must also be noexcept.
If you have inheriting constructors, these will be noexcept if the basic class constructor is no
accept.
And if we let the compiler synthesize special member functions for us, these will automatically be
noexcept, if the version in the base class is noexcept.
We can also make a child member function more exception safe than the parent's, but not the other way
round.
If we have a virtual function in the base case, which can throw, we can write an override in the child class, which
is noexcept.
But you cannot go the other way.
You cannot have a noexcept function in the base class and then have a child override which throws exceptions.
So that is similar to const.
You can make the child version more const, but you cannot make it less than the parent's.
And finally, if you do not make destructors noexcept, the compiler might do that for you anyway.
This can happen if all the members of your class have a noexcept destructor, or they are built-in types,
and all the parent classes of your class have a noexcept destructor. In that case,
the compiler will also assume that your destructor is noexcept.
So if you have existing code from before C++ 11, which does not use noexcept, then you just have
to recompile this, and the destructors will now be noexcept.
So you get the benefit of that, without having to modify your code.
If you are writing new code, though, it is better to write noexcept. It is always better to make things
explicit if you can.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!