기본 패턴
cpp
try {
throw std::runtime_error("failed");
} catch (const std::exception& ex) {
std::cout << ex.what() << "\n";
}설명
- 예외는 현재 함수가 직접 처리하기 어려운 오류를 호출자 쪽으로 전달하는 메커니즘입니다.
throw로 예외를 던지면 스택을 따라 올라가며 적절한catch를 찾고, 그 과정에서 지역 객체들은 소멸자를 통해 정리됩니다.- 바로 이 점 때문에 C++에서 RAII가 중요한데, 예외가 발생해도 자원 정리가 자동으로 되도록 설계할 수 있기 때문입니다.
- catch는 보통
const std::exception&처럼 참조로 받는 편이 복사 비용과 다형성 측면에서 유리합니다. - 예외는 강력하지만 제어 흐름을 숨길 수도 있으므로, "정말 예외 상황인가"와 "복구 가능한가"를 구분해 쓰는 편이 좋습니다.
짧은 예제
cpp
#include <exception>
#include <iostream>
#include <stdexcept>
int divide(int a, int b) {
if (b == 0) {
throw std::invalid_argument("division by zero");
}
return a / b;
}
int main() {
try {
std::cout << divide(10, 0) << "\n";
} catch (const std::exception& ex) {
std::cout << ex.what() << "\n";
}
}빠른 정리
| 항목 | 설명 |
|---|---|
throw | 예외를 발생시킴 |
try | 예외 가능성이 있는 코드를 감쌈 |
catch | 특정 예외를 처리 |
| stack unwinding | 예외 전파 중 지역 객체 소멸자가 호출됨 |
| RAII 관계 | 예외가 나도 자원 정리가 자동으로 되게 설계 가능 |
주의할 점
예외가 날 수 있는 코드에서 raw 자원을 직접 관리하면 누수가 생기기 쉽습니다. 예외 안전성을 확보하려면 스마트 포인터나 RAII 래퍼를 함께 쓰는 편이 좋습니다.