Skip to content
  • noexcept & Exception Safety · C++

noexcept & Exception Safety

LearnViaNotes @learnvianotes· 2 min read

noexcept promises a function won't throw — enabling optimisations like moving elements during vector growth. Exception-safety guarantees describe what state is left behind when something does throw.

noexcept

C++
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

int safeAdd(int a, int b) noexcept { return a + b; }
void mayThrow() { throw 1; }

template <typename T>
void swapValues(T& a, T& b) noexcept(std::is_nothrow_move_constructible_v<T>) {   // conditional
    T tmp = std::move(a);
    a = std::move(b);
    b = std::move(tmp);
}

int main() {
    std::cout << std::boolalpha
              << noexcept(safeAdd(1, 2)) << ' '          // noexcept operator: compile-time query
              << noexcept(mayThrow()) << ' '
              << std::is_nothrow_move_constructible_v<std::string> << ' '
              << std::is_nothrow_move_constructible_v<std::vector<int>> << '\n';
    std::string a = "x", b = "y";
    swapValues(a, b);
    std::cout << a << b << '\n';
}
Output
true false true true
yx
C++ — throwing from noexcept terminates
#include <stdexcept>
void promise() noexcept {
    throw std::runtime_error("broken promise");   // compiles, but calls std::terminate at run time
}
int main() { promise(); }
  • Destructors, operator delete and (by default) compiler-generated move operations of well-behaved members are noexcept.

  • Mark move constructors/assignments and swap noexcept — containers depend on it.

  • Don't mark functions noexcept if they might throw someday; removing it later breaks callers that relied on it.

The exception-safety guarantees

GuaranteePromise if an exception is thrownExample
No-throwNever throwsDestructors, swap, move operations
StrongCommit-or-rollback: state is unchangedvector::push_back (when the move ctor is noexcept or copyable)
BasicNo leaks, invariants hold, but state may have changedMost operations
NoneAnything goes — avoidCode with raw new/delete

Getting the strong guarantee: copy-and-swap

C++
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

class Inventory {
    std::vector<std::string> items_;
public:
    void addAll(const std::vector<std::string>& newItems) {
        std::vector<std::string> copy = items_;          // 1. work on a copy
        for (const auto& it : newItems) {
            if (it.empty()) throw std::invalid_argument("empty item");
            copy.push_back(it);
        }
        items_.swap(copy);                               // 2. commit with a no-throw swap
    }
    std::size_t size() const { return items_.size(); }
};

int main() {
    Inventory inv;
    inv.addAll({"pen", "ink"});
    try { inv.addAll({"cap", "", "pad"}); } catch (const std::exception& e) { std::cout << e.what() << '\n'; }
    std::cout << inv.size() << '\n';                      // still 2: nothing half-added
}
Output
empty item
2

Why are destructors implicitly noexcept?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report