zoukankan      html  css  js  c++  java
  • (原创)用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,欢迎大家来交流技术。

  • 相关阅读:
    封装
    Android 使用AS编译出错:找不到xx/desugar/debug/66.jar (系统找不到指定的文件。)
    Android 使用AS编译出错:Error: Duplicate resources
    Android报错:The processing instruction target matching "[xX][mM][lL]" is not allowed.
    Android 用versionName判断版本大小(是否进行版本更新)
    Android 重写物理返回键,在h5页面中返回上一个界面
    Jetpack 由 WordPress.com 出品
    centos配置虚拟主机
    linux下安装apache与php;Apache+PHP+MySQL配置攻略
    Global Translator
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3421333.html
Copyright © 2011-2022 走看看