RAII 의 ScopeExit 를 교묘 하 게 사용 합 니 다.
리 소스 Acquisition Is Initialization,자원 획득 즉 초기 화,자원 의 생명주기 와 한 대상 의 생명주기 연결,예 를 들 어 일부 자원 을 클래스 에 봉 하여 구조 함수 에서 자원 을 요청 하고 분석 함수 에서 자원 을 방출 하 며 이상 을 던 지지 않 습 니 다.한 대상 은 생명주기 가 끝 날 때 자동 으로 분석 함 수 를 호출 합 니 다.즉,자원 의 생명주기 와 한 대상 의 생명주기 가 연결 되 어 있다.
레이 이의 응용
다음 코드 참조:
std::mutex mutex;
void func() {}
void NoRAII() {
mutex.lock();
func();
if (xxx) {
mutex.unlock();// unlock(), unlock
return;
}
...
mutex.unlock();
}
void RAII() { // unlock
std::lock_guard<std::mutex> lock(mutex);
func();
if (xxx) {
return;
}
...
return;
}
RAII 의 응용 이 매우 많 습 니 다.C++의 STL 은 기본적으로 RAII 규범 을 따 릅 니 다.전형 적 인 예 를 들 어 vector,string,lockguard, unique_lock, shared_ptr, unique_ptr 등,여기 서 이러한 STL 의 사용 을 소개 하지 않 을 것 입 니 다.여러분 도 모두 사용 할 것 이 라 고 믿 습 니 다.관련 수요 가 있 으 면 메 시 지 를 남 길 수 있 습 니 다.레이 이의 유용 성
최근 boost 의 ScopeExit 를 연구 한 결과 이것 은 매우 고 급 스 러 운 특성 임 을 발견 하 였 습 니 다.RAII 특성 을 이용 하여 역할 영역 이 끝 날 때 열 린 자원 을 자동 으로 닫 거나 청소 작업 을 할 수 있 습 니 다.유 니 크 와 유사 합 니 다.ptr,하지만 유 니 크ptr 가 편리 합 니 다.delete 함 수 를 사용자 정의 할 필요 가 없습니다.
ScopeExit 없 으 면
void test () {
char *test = new char[100];
if (a) {
delete[] test; // count 1
return;
}
xxx;
if (b) {
delete[] test; // count 2
return;
}
...
delete[] test; // count 3
}
ScopeExit 를 사 용 했 습 니 다.
void test () {
char *test = new char[100];
std::ofstream ofs("test.txt");
ScopeExit {
delete[] test; // test delete[]
ofs.close(); // , ,ofstream
};
if (a) {
return;
}
xxx;
if (b) {
return;
}
...
}
물론 정상 적 인 C++코드 는 누 드 포인터 사용 을 권장 하지 않 고 스마트 포인터 로 자원 을 신청 할 수 있 습 니 다.여 기 는 예 를 들 어 ScopeExit 를 사용 해도 파일 자원 의 닫 기 등 을 처리 할 수 있 습 니 다.두 코드 를 비교 한 후에 우열 정 도 는 분명 하 다.ScopeExit 를 사용 하지 않 으 면 return 전에 여러 번 자원 청 소 를 해 야 하고 ScopeExit 를 사용 하면 한 번 의 성명 만 한 후에 역할 영역 이 끝 난 후에 관련 자원 청 소 를 자동 으로 할 수 있 으 며 편리 하고 오류 가 발생 하지 않 는 다.
ScopeExit 실현
여기 서 boost 를 참고 하여 C++11 을 사용 하여 ScopeExit 체 제 를 실현 하 였 습 니 다.
class ScopeExit {
public:
ScopeExit() = default;
ScopeExit(const ScopeExit&) = delete;
void operator=(const ScopeExit&) = delete;
ScopeExit(ScopeExit&&) = default;
ScopeExit& operator=(ScopeExit&&) = default;
template <typename F, typename... Args>
ScopeExit(F&& f, Args&&... args) {
func_ = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}
~ScopeExit() {
if (func_) {
func_();
}
};
private:
std::function<void()> func_;
};
#define _CONCAT(a, b) a##b
#define _MAKE_SCOPE_(line) ScopeExit _CONCAT(defer, line) = [&]()
#undef SCOPE_GUARD
#define SCOPE_GUARD _MAKE_SCOPE_(__LINE__)
사용 방식 은 다음 과 같 습 니 다.
void test () {
char *test = new char[100];
std::ofstream ofs("test.txt");
SCOPE_GUARD{
delete[] test;
ofs.close();
};
if (a) {
return;
}
...
if (b) {
return;
}
...
}
레이 이 는 또 재 미 있 는 묘용 이 많 으 니 추 후 소개 도 할 예정 이 니 계속 지 켜 봐 주세요.RAII 의 ScopeExit 를 교묘 하 게 사용 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 RAII 의 묘 용 ScopeExit 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!