In C++, marking a function as noexcept is a contract with the compiler. By promising that a function will never throw an exception, you allow the compiler to perform optimizations that would otherwise be impossible.
Let's look at noexcept syntax, terminate rules, and vector move optimizations.
The `noexcept` Specifier: A Strict Contract
You declare a function as non throwing by appending noexcept to its signature. If a function marked noexcept does throw an exception at runtime, C++ does not attempt to unwind the stack. It immediately calls std::terminate to abort the application. Because stack unwinding is bypassed, the compiler can generate smaller, faster code frames.
Vector Move Optimization: The Copy Fallback
The most critical application of noexcept is for move constructors. When a std::vector runs out of capacity, it must reallocate its heap buffer. To do this, it allocates a new buffer and moves elements from the old buffer to the new one.
If a move constructor throws an exception halfway through this reallocation, the vector cannot roll back the moves easily, which would violate the strong exception safety guarantee. To prevent this, the C++ standard library checks if your class has a noexcept move constructor:
* If marked noexcept: The vector moves the elements to the new buffer in constant time.
* If NOT marked noexcept: The vector falls back to slow copies, copying every element and then deleting the old ones, to preserve exception safety.
* The Delivery Driver Metaphor: Imagine a shipping manager who only accepts delicate glassware from a delivery driver if the driver guarantees they will not drop them. If the driver cannot promise safety (noexcept), the manager orders a slow, heavily padded conveyor belt instead (slow copy fallback) to ensure nothing breaks.