Throwing and Catching Exceptions
The noexcept keyword declares that a function should never throw an exception.
Try it: try / except / else / finally
How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.
How it works
- Statements in try run until one raises an exception; the rest of try is skipped.
- Python checks the except clauses in order and runs the first one whose type matches.
- If nothing was raised, the else block runs instead.
- finally runs in every case.
Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.
Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.
Loading the simulation…
Why a Function Might Promise Silence
Most functions are written on the assumption that something might go wrong. A function may call other functions, request memory, or read input, and any of those operations can fail. When they do, an exception may be thrown. The normal design of an exception-aware program is to let the exception travel outward until some part of the program is prepared to handle it.
Some functions, however, are meant to do their job without ever raising an exception at all. A function that performs only simple, self-contained work may be one of them. The noexcept keyword exists so that the author of such a function can say so directly in the function's declaration. Instead of hoping that callers will assume the function is safe, the author writes the expectation into the code itself.
The rest of this article follows one scenario closely. Before reading the explanation, you will be asked to predict what happens when a noexcept function fails, and then you will check your prediction against the rules the language follows.
Following One Scenario Step by Step
Consider a function named user() that is declared noexcept. Its author expects it to succeed every time. Inside user(), a helper operation runs, and that helper fails and throws an exception. The main function called user(), and main has a catch block ready to handle failures.
What do you think happens?
The helper inside user() throws an exception. Does main's catch block run, does the program keep going normally, or does something else happen?
Reveal answer
terminate() is called and the program is stopped immediately. main's catch block never runs.
The source states that when a noexcept function still throws, the language does not carry the exception out to the caller. Instead, terminate() is called and immediately terminates the program.
Trace the path in the diagram. The exception starts in the helper operation, which is running inside user(). It attempts to leave user(). Because user() is declared noexcept, the exception does not continue upward to main as it would from an ordinary function. The catch block in main sits in the caller, but the language never hands the exception to it. The program is terminated at that point, so the catch block has no chance to run.
The noexcept Declaration as a Statement of Intent
The noexcept keyword declares that a function should never throw an exception.
The keyword is best understood as a statement of intent that travels with the function. Anyone who reads the declaration learns that the function is expected never to throw. That information matters to the people who call the function and to the people who maintain it, because it tells them what they can assume about the function's behavior.
The important word in the definition is should. The declaration does not make a function unable to throw. It records the author's expectation, and the rest of the program is built on top of that expectation. This is why declaring a function noexcept is a decision about the function's design, not a decoration added at the end.
What Happens When the Promise Breaks
Suppose a function is declared noexcept, but during its execution an exception is still thrown. The language does not quietly carry that exception out to the caller, as it would for an ordinary function. Instead, the standard-library function terminate() is called, and it immediately terminates the program. A broken noexcept promise therefore has a visible and immediate consequence.
Two versions of user()
The same helper operation fails in two versions of user(). In version A, user() is an ordinary function. In version B, user() is declared noexcept. What happens to the exception in each version?
- 1Version A: ordinary function
The exception leaves
user()and is carried out to the caller, main. main's catch block has the chance to handle it. - 2Version B: noexcept function
The exception is thrown inside
user(), which is declared noexcept. The language does not carry the exception out to main. - 3Terminate
terminate()is called and immediately terminates the program. The catch block in main never runs.
The only difference between the two versions is the declaration, yet the outcome is completely different: one version can be recovered by the caller, the other stops the program.
Choosing Where noexcept Belongs
Because a broken promise stops the program, noexcept should be used only where the function's author has a real basis for expecting no exceptions. Most of the time an author cannot be sure that nothing inside a function will ever fail. The useful habit is to ask, before writing the keyword, what would happen if the function did throw.
| Question | Good noexcept candidate | Poor noexcept candidate |
|---|---|---|
| What work does it do? | Simple, self-contained work | Calls other functions whose behavior the author does not control |
| Can its operations fail? | The author is confident no failure can occur | Memory requests or input operations that can go wrong |
| If it throws, should the program recover? | No: the author expects the work to succeed | Yes: the program should be able to recover |
| What does the keyword say? | An accurate description of the expectation | A false promise that stops the program when broken |
Judging whether a function should carry the noexcept declaration
Mistakes Beginners Make with noexcept
Common mistake Treating noexcept as protection against failure
What it looks likeMarking a function noexcept and assuming that the function can no longer fail.
Why it failsThe declaration does not make a function unable to throw. It records an expectation, and the source says the keyword does not shield a program from failure.
Do this insteadUse noexcept to document an expectation that the author has good reason to hold, and still make sure the work really is expected to succeed.
Common mistake Marking a function noexcept because it usually succeeds
What it looks likeA function that calls a memory request or reads input is marked noexcept since it works in most test runs.
Why it failsMemory requests and input operations can go wrong, and when they do an exception may be thrown. A promise that holds most of the time is still broken when the failure occurs.
Do this insteadLeave the keyword off when the function's work includes operations that can fail, and let exceptions propagate to a caller that can handle them.
Common mistake Expecting a caller's catch block to handle a noexcept throw
What it looks likeWrapping a call to user() in a try and catch, then assuming the catch will handle any failure inside user().
Why it failsWhen a noexcept function throws, the exception is not carried out to the caller.
terminate()is called instead, so the catch block never runs.Do this insteadHandle expected failures inside the code that can produce them, or remove noexcept from functions where recovery by the caller matters.
Practice: Judging a Function
A function named user() is declared noexcept. Inside it, a helper operation requests memory and reads a line of input. If the input operation fails and throws an exception, trace what happens to the exception, and state whether the caller's catch block can handle it. Then decide whether the noexcept declaration is an accurate statement of intent for this function.
Hints
- Start from the rule: when a noexcept function still throws, is the exception carried out to the caller?
- Look at the kinds of operations the function performs. The source names memory requests and input operations as things that can go wrong.
- Ask whether the author has a real basis for expecting no exceptions before deciding whether the keyword is accurate.
Key Takeaways from the noexcept Promise
- 1The noexcept keyword declares that a function should never throw an exception, and it records the author's expectation.
- 2If a noexcept function still throws, the exception is not carried out to the caller.
terminate()is called and immediately terminates the program. - 3Because a broken promise stops the program, noexcept should be used only where the author has a real basis for expecting success.
- 4Before writing the keyword, ask what would happen if the function did throw. If the program should be able to recover, leave noexcept off.
At a glance
- The noexcept keyword declares that a function should never throw an exception, and it is the author's responsibility to make that true.
- When an exception escapes a noexcept function, it is not carried out to the caller;
terminate()is called and the program stops immediately. - A caller's catch block cannot rescue a broken noexcept promise, because the exception never reaches the caller.
- Use noexcept only for functions whose work the author genuinely expects to succeed, and never as protection against failure.