ScopeGuard : 安全清理資源

轉載自(http://www.cnblogs.com/tonychen-tobeTopCoder/p/5222178.html

class ScopeGuard
{
public:
    explicit ScopeGuard(std::function<void()> onExitScope)
        : onExitScope_(onExitScope), dismissed_(false)
    { }

    ~ScopeGuard()
    {
        if (!dismissed_)
        {
            onExitScope_();
        }
    }

    void Dismiss()
    {
        dismissed_ = true;
    }

private:
    std::function<void()> onExitScope_;
    bool dismissed_;

private: // noncopyable
    ScopeGuard(ScopeGuard const&);
    ScopeGuard& operator=(ScopeGuard const&);
};

爲了在管理多個資源時不用花精力想變量名,可以定義幾個宏

#define SCOPEGUARD_LINENAME_CAT(name, line) name##line
#define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line)
#define ON_SCOPE_EXIT(callback) ScopeGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback)

其中##是連接符,LINE是編譯器自帶的宏,指的是源代碼的行號。這樣就會自動生成變量名爲”EXIT行號”。
應用如下

class A {
public:
    int a;
    A(int i) :a(i) {}
};

void EraseA(A &a)
{
    a.a = 0;
    cout << "eraseA" << endl;
}

int main()
{
    A a(2);
    ON_SCOPE_EXIT([&] { EraseA(a); });
    return 0;
}

程序結束時輸出 eraseA
Dismiss()函數作用是爲了支持rollback模式,例如:

ScopeGuard onFailureRollback([&] { /* rollback */ });
... // do something that could fail
onFailureRollback.Dismiss();

如果“do something”的代碼出錯,就執行析構函數中的rollback邏輯。如果代碼順利運行,就將dismissed_設爲true,這樣在退出作用域時就不會執行rollback操作了。

lambda表達式用於創建匿名函數對象語法格式如下

[捕獲列表] (函數參數) mutable或exception聲明 ->返回類型 {函數體};

捕獲列表是一個lambda所在函數中定義的局部變量的列表,可以爲空,上文的[&]表示默認使用引用傳值,如果用[=]則表示默認使用值傳遞。

最簡單的使用方法如下

auto f = [] {return 42;};
cout<<f()<<endl;

結果打印42。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章