(原創)用c++11實現簡潔的ScopeGuard


  ScopeGuard的作用是確保資源面對異常時總能被成功釋放,就算沒有正常返回。慣用法讓我們在構造函數里獲取資源,當因為異常或者正常作用域結束,那么在析構函數里釋放資源。總是能釋放資源。如果沒有異常拋出則正常結束,只是有異常發生或者沒有正常退出時釋放資源。關於ScopeGaurd的概念想多了解一點的童鞋點這里這里。c#中的ScopeGuard比較簡單,通過using初始化或者通過finally就可以做到,c++中需要自己去實現。

  c++中設計ScopeGuard的關鍵技術:通過局部變量析構函數來管理資源,根據是否是正常退出來確定是否需要清理資源。用c++11做很簡單。

template <typename F>
class ScopeGuard
{
public:
    explicit ScopeGuard( F && f) : m_func(std::move(f)), m_dismiss(false){}
    explicit ScopeGuard(const F& f) : m_func(f), m_dismiss(false){}

    ~ScopeGuard()
    {
        if (!m_dismiss)
            m_func();
    }

    ScopeGuard(ScopeGuard && rhs) : m_func(std::move(rhs.m_func)), m_dismiss(rhs.m_dismiss){rhs.Dismiss();}

    void Dismiss()
    {
        m_dismiss = true;
    }

private:
    F m_func;
    bool m_dismiss;

    ScopeGuard();
    ScopeGuard(const ScopeGuard&);
    ScopeGuard& operator=(const ScopeGuard&);

//template<class... Args>
//auto Run(Args&&... args)->typename std::result_of<F(Args...)>::type
//{
//  return m_func(std::forward<Args>(args)...);
//}

};

template <typename F>
ScopeGuard<typename std::decay<F>::type> MakeGuard(F && f)
{
  return ScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
}

測試代碼:

void TestScopeGuard()
{    
    std::function < void()> f = [] { cout << "cleanup from unnormal exit" << endl; };
    //正常退出
    {        
        auto gd = MakeGuard(f);
        //...
        gd.Dismiss();
    }

    //異常退出
    {
        auto gd = MakeGuard(f);
        //...
        throw 1;
    }

    //非正常退出
    {
        auto gd = MakeGuard(f);
        return;
        //...
    }
}

  通過測試程序可以知道,當程序沒有發生異常正常退出時,需要調用一下Dismiss函數,以解除ScopeGuard,當程序異常退出時,會進入異常處理函數去釋放相應資源,實現ScopeGuard的目的。

c++11 boost技術交流群:296561497,歡迎大家來交流技術。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM