RAII(Resource Acquisition Is Initialization)는 C++에서 자원의 수명을 객체의 수명에 바인딩하는 관용 패턴이다. 생성자에서 자원을 획득하고, 소멸자에서 해제한다.
RAII 원리
cpp
class FileHandle {
FILE* file;
public:
explicit FileHandle(const char* path, const char* mode) {
file = fopen(path, mode);
if (!file) throw std::runtime_error("파일 열기 실패");
}
~FileHandle() {
if (file) fclose(file); // 소멸 시 자동 해제
}
// 복사 금지, 이동 허용
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
FILE* get() { return file; }
};
void process() {
FileHandle f("data.txt", "r");
// 예외 발생해도 소멸자 실행 보장
} // f 소멸 → fclose 자동 호출
스마트 포인터
cpp
# include <memory>
// unique_ptr: 단독 소유권
auto ptr = std::make_unique<int>(42);
// delete 불필요, 스코프 이탈 시 자동 해제
// shared_ptr: 공유 소유권 (참조 카운팅)
auto s1 = std::make_shared<std::vector<int>>(10);
auto s2 = s1; // 참조 카운트 2
// 마지막 소유자가 해제될 때 delete
// weak_ptr: 순환 참조 방지
std::weak_ptr<int> w = s1;
if (auto locked = w.lock()) {
// 여전히 살아있을 때만 사용
}
잠금 관리
cpp
std::mutex mtx;
void safe_function() {
std::lock_guard<std::mutex> lock(mtx); // 생성 시 lock
// critical section
} // 소멸 시 자동 unlock (예외 안전)
// unique_lock: 더 유연한 버전
std::unique_lock<std::mutex> ulock(mtx);
ulock.unlock(); // 수동 해제 가능
ulock.lock(); // 재획득
RAII vs. try-finally
| 특성 | RAII (C++) | try-finally (Java/Python) |
|---|
| 코드량 | 적음 | 매번 작성 |
| 예외 안전 | 자동 | 수동 |
| 중첩 자원 | 자연스러움 | 복잡 |
| 성능 | 제로 오버헤드 | 약간 오버헤드 |
관련 개념