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。
原文链接: https://www.cnblogs.com/tonychen-tobeTopCoder/p/5222178.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/229237

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 下午2:15
下一篇 2023年2月13日 下午2:15

相关推荐