ReviseAlgo Logo

Exception Handling

noexcept Specifier

Signal non-throwing behavior to the compiler and standard library containers to optimize move operations.

Interview: How noexcept optimizes std::vector resize, the difference between specifier and operator, and the consequences of throwing from noexcept.

Last Updated: June 13, 2026 9 min read

Introduced in C++11, the noexcept specifier declares that a function will not throw exceptions. This allows the compiler to generate more optimized code and allows standard library containers (like std::vector) to use move semantics safely.

Optimization

The compiler does not need to generate stack unwinding tables for noexcept functions, reducing code size.

Move Semantics

std::vector will only move elements during resize if the move constructor is marked noexcept; otherwise, it copies them.

noexcept Operator

A compile-time operator that checks if an expression is declared to not throw. Used in template metaprogramming.

Why noexcept Matters for std::vector Resize

To maintain the Strong Exception Safety Guarantee during reallocation, std::vector::resize must be careful. If a move constructor throws an exception halfway through reallocating, the original vector elements are corrupted.

Therefore, std::vector checks at compile time using std::is_nothrow_move_constructible. If the type's move constructor is marked noexcept, it will use move semantics. If not, it falls back to copying the elements, which is slower but exception-safe.

Code Walkthrough

Demonstrates the performance implications of marking move constructors as noexcept.

#include <iostream>
#include <vector>
#include <type_traits>

class Item { public: Item() = default; Item(const Item&) { std::cout << "Copy constructor\n"; }

// Marked noexcept: std::vector will use this during resizing Item(Item&&) noexcept { std::cout << "Move constructor\n"; } };

class HeavyItem { public: HeavyItem() = default; HeavyItem(const HeavyItem&) { std::cout << "Heavy Copy\n"; }

// NOT marked noexcept: std::vector falls back to copying HeavyItem(HeavyItem&&) { std::cout << "Heavy Move\n"; } };

int main() { std::cout << "--- Item (noexcept Move) ---" << std::endl; std::vector<Item> items; items.emplace_back(); items.emplace_back(); // Resizes here: invokes move constructor

std::cout << "\n--- HeavyItem (throwing Move) ---" << std::endl; std::vector<HeavyItem> heavyItems; heavyItems.emplace_back(); heavyItems.emplace_back(); // Resizes here: falls back to copy constructor

return 0; }

Interview-Relevant Information

Q: What happens if a function marked noexcept throws an exception?
Answer: If a function explicitly declared as noexcept attempts to propagate an exception, the runtime calls std::terminate immediately to abort the application. The stack is not guaranteed to be fully unwound, meaning object destructors might not be called before the crash.

Q: What is the conditional noexcept specifier?
Answer: You can declare conditional throwing behavior on template functions by passing a boolean expression to the specifier: noexcept(condition). For example, void swap(T& a, T& b) noexcept(noexcept(a.swap(b))) specifies that swap is non-throwing only if the underlying type's swap operation is non-throwing.

Quick Checklist

Did you mark move constructors and move assignment operators as noexcept? Do you swap functions with noexcept? If yes, you are optimizing your classes for STL containers.

Use Cases

Optimizing performance inside STL container reallocations (vector resize, deque insertions).

Declaring move constructors, move assignments, destructors, and swap functions to improve compiler optimization paths.

Common Mistakes

Throwing exceptions inside a function declared noexcept, leading to immediate std::terminate crashes.

Omitting noexcept on move constructors, causing standard containers to copy elements during reallocation.