Skip to content
  • Exceptions · C++

Exceptions

LearnViaNotes @learnvianotes· 3 min read

throw signals an error that the current function can't handle; the stack unwinds (destroying locals) until a matching catch is found.

throw / try / catch

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

double divide(double a, double b) {
    if (b == 0) throw std::invalid_argument("division by zero");
    return a / b;
}

int parseAge(const std::string& s) {
    int age = std::stoi(s);                          // may throw invalid_argument / out_of_range
    if (age < 0 || age > 150) throw std::out_of_range("age " + s + " out of range");
    return age;
}

int main() {
    try {
        std::cout << divide(10, 4) << '\n';
        std::cout << divide(1, 0) << '\n';           // throws — the rest of the try is skipped
        std::cout << "never printed\n";
    } catch (const std::invalid_argument& e) {
        std::cout << "invalid: " << e.what() << '\n';
    }

    for (std::string input : {"42", "abc", "200"}) {
        try {
            std::cout << parseAge(input) << '\n';
        } catch (const std::out_of_range& e) {       // most specific first
            std::cout << "range: " << e.what() << '\n';
        } catch (const std::exception& e) {          // any standard exception
            std::cout << "error: " << e.what() << '\n';
        } catch (...) {                              // anything at all
            std::cout << "unknown\n";
        }
    }
}
Output
2.5
invalid: division by zero
42
error: stoi: no conversion
range: age 200 out of range

The standard hierarchy

ExceptionThrown by / used for
std::exceptionBase of all — has virtual const char* what()
std::logic_error → invalid_argument, out_of_range, length_error, domain_errorBugs detectable before running: bad arguments, vector::at, stoi
std::runtime_error → range_error, overflow_error, system_errorErrors only detectable at run time: I/O, OS
std::bad_allocnew failed
std::bad_cast, std::bad_optional_access, std::bad_variant_access, std::bad_function_callMisused library types

Custom exceptions & rethrowing

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

class HttpError : public std::runtime_error {
public:
    HttpError(int code, const std::string& msg)
        : std::runtime_error(msg), code_(code) {}
    int code() const noexcept { return code_; }
private:
    int code_;
};

void fetch() { throw HttpError(404, "page not found"); }

void handler() {
    try {
        fetch();
    } catch (const HttpError& e) {
        std::cout << "log: " << e.code() << '\n';
        throw;                                       // rethrow the SAME exception object
    }
}

int main() {
    try { handler(); }
    catch (const std::exception& e) { std::cout << "top level: " << e.what() << '\n'; }
}
Output
log: 404
top level: page not found

Stack unwinding

C++
#include <iostream>
#include <stdexcept>
struct Guard {
    const char* name;
    ~Guard() { std::cout << "cleanup " << name << '\n'; }
};
void inner() { Guard g{"inner"}; throw std::runtime_error("fail"); }
void outer() { Guard g{"outer"}; inner(); }
int main() {
    try { outer(); } catch (const std::exception& e) { std::cout << "caught " << e.what() << '\n'; }
}
Output
cleanup inner
cleanup outer
caught fail

What happens when an exception is thrown?

Exceptions vs error codes?

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