예외는 함수가 자기 계약대로 일을 끝내지 못했을 때, 호출 스택을 따라 그 사실을 보내는 장치다. `throw`한 예외를 누군가 `catch`할 때까지 지역 객체는 소멸한다.

C++ 22. 예외와 예외 안전의 핵심 흐름도
그림. 예외 중에도 RAII 객체가 자원을 정리하도록 설계한다.

던지고 잡기

#include <stdexcept>

int depth_of(int n) {
    if (n < 1) throw std::invalid_argument("depth");
    return n;
}

try {
    depth_of(0);
} catch (const std::exception& ex) {
    // ex.what()로 이유를 읽는다
}

예외를 정상 흐름의 분기처럼 남용하면 읽기가 어려워진다. 실패가 흔한 API는 `std::optional`, `std::expected`(C++23)처럼 값을 반환하는 편이 맞을 수 있다. 한 프로젝트 안에서는 방식을 섞지 않는다.

안전 수준

기본 보장은 예외가 나도 객체가 파괴 가능하고 자원이 새지 않는 상태다. 강한 보장은 연산이 성공하거나, 실패해도 상태가 그대로다. `noexcept` 함수에서 예외가 빠져나가면 프로그램은 종료된다. 소멸자와 이동은 예외를 던지지 않는 쪽이 맞다. 소멸자가 예외를 던지면, 이미 다른 예외를 처리 중일 때 프로그램을 끝낸다.