RAII란 뭘까요? Research Assistant 2형?
Resource Acquisition is initialization, "자원 획득은 초기화다"의 두문자어(acronym)입니다.
이게 뭔소리일까요; 알아봅시다
RAII (Resource Acquisition is Initialization)
RAII는 오브젝트의 생명주기에 관련된 내용입니다. C++에서 스택 메모리에 있는 변수들은 스코프를 빠져나오게 되면 소멸자 호출을 통해 stack unwinding이 진행됩니다. Exception이 던져지더라도 소멸자 호출은 보장됩니다.
따라서 Exception-safe 코드를 만들 때 꼭 필요한 개념입니다.
#include <fstream>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <string>
void WriteToFile(const std::string& message) {
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
std::ofstream file("example.txt");
if (!file.is_open()) {
throw std::runtime_error("unable to open file");
}
file << message << std::endl;
// |file| will be closed first when leaving scope (regardless of exception)
// mutex will be unlocked second (from lock destructor) when leaving scope
// (regardless of exception).
}
위키에 있는 예제입니다. std::lock_guard
가 RAII를 이용한 좋은 예시입니다. mutex에 락을 했는데 예외가 던져지면 락이 풀리지 않아 데드락이 발생합니다. lock_guard를 사용하면 소멸자에서 락을 푸니 exception-safe하게 됩니다.
fstream도 동일합니다. open 후 예외가 던져지면 소멸자에서 close 해버립니다.
주의사항
RAII는 스택에 할당된 객체에만 적용됩니다.
std::string firstLineOf(const char* filename){
OpenFile f("boo.txt"); //stack allocated
return f.readLine();
//File closed here. `f` goes out of scope and destructor is run.
}
std::string firstLineOf(const char* filename){
OpenFile* f = new OpenFile("boo.txt"); //heap allocated
return f->readLine();
//DANGER WILL ROBINSON! Destructor is never run, because `f` is never
//deleted
}
힙에 동적할당된 객체에는 적용되지 않습니다. 이럴때는 스마트 포인터를 써야 좋겠죠
또한 예외가 어딘가에서 catch 되었을 때만 stack unwinding이 보장됩니다.
참고자료
반응형
'프로그래밍 > C++' 카테고리의 다른 글
[C++17] std::any에 대해 (0) | 2020.10.03 |
---|---|
Visual studio Google Test 사용 예제 (0) | 2020.08.09 |
C++ std::thread (0) | 2020.07.25 |
C++ std::unique_ptr 2차원 배열 만들기 (0) | 2020.07.17 |
C++11 implicit narrowing conversion (축소 변환) 방지하는 법 (0) | 2020.06.23 |