zoukankan      html  css  js  c++  java
  • C++11的资源管理:泛化的RAII

      RAII被认为是c++资源管理的最佳范式,但是c++98中用RAII必须为要管理的资源写一个类,这样一来RAII的使用就有些繁琐了。C++11有了lambda和function后,我们就可以编写泛化的RAII,实现ScopeGuard,优雅地解决这个问题。本文主要参考刘未鹏的博客

      主要代码如下 

    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。

  • 相关阅读:
    将结构体存入Access数据库
    得到当前活动窗体的标题
    Scrapy各项命令说明
    session & viewstate
    网页设计中的默认字体样式详解
    ie6中href设为javascript:void(0)页面无法提交
    < ![if IE]> < ![endif]> 条件注释
    编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的区别
    Web字体的运用与前景
    jQuery和web.py美元符号($)冲突的解决方法
  • 原文地址:https://www.cnblogs.com/tonychen-tobeTopCoder/p/5222178.html
Copyright © 2011-2022 走看看