If you skim through the remaining rules to error handling, you often read the word noexcept. Before I write about the rules to error handling, I write first about the noexcept specifier and the noexcept operator in this post.

noexcept

noexcept exists in two forms since C++11: as a specifier and as an operator. The C++ core guidelines uses the specifier.

noexcept as specifier

By declaring a function, a method, or a lambda-function as noexcept, you specify that these does not throw an exception and if they throw, you do not care and let the program just crash. For simplicity reasons, I will write about function but mean also methods and function templates. There are various ways to express your intention:

voidfunc1() noexcept; // does not throwvoidfunc2() noexcept(true); // does not throwvoidfunc3() throw(); // does not throwvoidfunc4() noexcept(false); // may throw

The noexcept specification is equivalent to the noexcept(true) specification. throw() is equivalent to noexcept(true) but was deprecated with C++11 and will be removed with C++20. In contrast, noexcept(false) means that the function may throw an exception. The noexcept specification is part of the function type but can not be used for function overloading.

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. noexcept may not call std::unexpectedand may not unwind the stack. The initialisation of a container may cheap move the elements into the container if the move constructor is declared as noexcept. If not declared as noexcept, the elements may be expensive copied into the container.

Each function in C++ is either non-throwing or potentially throwing. Potentially throwing means:

The function may use a function that may throw.

The function is declared without a noexcept specification.

The function uses a dynamic_cast to a reference type.

There is an exception to the rule 2, that functions are potentially throwing if they have no noexcept specification. These exceptions include the following six special member functions. They are implicitly non-throwing.

Default constructor and destructor

Move and copy constructor

Move and copy assignment operator

This special six member such as the destructor can only be non-throwing if all destructors of the attributes and the bases-classes are non-throwing. Of course, the corresponding statement will hold for the five other special member functions.

What happens when you throw an exception in a function which is declared as non-throwing? In this case,std::terminate is called. std::terminate calls the currently installed std::terminate_handler which calls std::abort by default.The result is an abnormal program termination.

For completeness, is want to present noexcept as operator.

noexcept as operator

The noexcept operator checks at compile-time if an expression does not throw an exception. The noexcept operator does not evaluate the expression. It can be used in a noexcept specifier of a function template to declare that the function may throw exceptions depending on the current type.

To make my description clear here is a simple example of a function template which copies it return value.

Of course, the most interesting line in this example is the line (1). In particular, the expression noexcept(noexcept(T(src)). The inner noexcept ist the noexcept operator and the outer the noexcept specifier. The expression noexcept(T(src)) checks in this case if the copy constructor is non-throwing.This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) because of the copy constructor of std::vector that may throw. Consequently, the expression (4) returns true and the expression (5) returns false.

Maybe you know about it. You can check at compile time with the help of the type traits library if a type T has a non-throwing copy constructor: std::is_nothrow_copy_constructible::value. Based on this predicate you can use instead of the noexcept operator the predicate from the type traits library:

If the throw is fired the memory is lost and you have a leak. The simple solution is to get rid of the ownership and make the C++ runtime to the direct owner of the object. Just create a local object or at least a guard as a local object. And you know the C++ runtime takes care of local objects. Here are three variations of this idea.

Get your e-book at leanpub:

The C++ Standard Library

Concurrency With Modern C++

Get Both as one Bundle

With C++11,C++14, and C++17 we got a lot of new C++ libraries. In addition, the existing ones are greatly improved. The key idea of my book is to give you the necessary information to the current C++ libraries in about 200 pages.

C++11 is the first C++ standard that deals with concurrency. The story goes on with C++17 and will continue with C++20.

I'll give you a detailed insight in the current and the upcoming concurrency in C++. This insight includes the theory and a lot of practice with more the 100 source files.

Get my books "The C++ Standard Library" (including C++17) and "Concurrency with Modern C++" in a bundle.

In sum, you get more than 600 pages full of modern C++ and more than 100 source files presenting concurrency in practice.