RAII 의 ScopeExit 를 교묘 하 게 사용 합 니 다.

3997 단어 RAIIScopeExit
레이 이 가 뭐야?
리 소스 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 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기