代码之家  ›  专栏  ›  技术社区  ›  The Quantum Physicist

什么是最短路径在C++ 11(或更新)创建RAII包装器而不必写一个新的类?

  •  10
  • The Quantum Physicist  · 技术社区  · 6 年前

    通常情况下,我需要一个简单的RAII包装器,但我不想为此创建一个全新的类,原因有很多,包括时间限制和组织问题。我的快速N脏解决方案如下。

    假设我想确保在作用域结束时,我想要一个布尔值切换回其原始状态:

    bool prevState = currState;
    currState      = newState;
    std::unique_ptr<int, std::function<void(int*)>> txEnder(new int(0), [&prevState](int* p) {
        currState = prevState;
        delete p;
    });
    

    此解决方案工作正常,但脏的部分是必须分配和取消分配该整数,以便 unique_ptr 工作并在销毁时调用自定义析构函数。

    有没有一个更干净的方法来做到这一点,而不必写一个完整的类,并摆脱 new 为傀儡 int ?

    4 回复  |  直到 6 年前
        1
  •  6
  •   mch    6 年前

    比你的好一点:你可以用 &prevState 在自定义析构函数中不删除它,因此不需要 new delete 一些事情:

    void foo(bool & currState, bool newState)
    {
        bool prevState = currState;
        currState      = newState;
        std::unique_ptr<bool, std::function<void(bool*)>> txEnder(&prevState, [&prevState, &currState](bool* p) {
            currState = prevState;
        });
        cout << "currState: " << currState << endl;
    }
    

    你也忘了捕捉 currState 在拉姆达。

    下面是一个例子: https://ideone.com/DH7vZu

        2
  •  7
  •   user7860670    6 年前

    你可以使用 BOOST_SCOPE_EXIT

    auto prevState{currState};
    currState = newState;
    BOOST_SCOPE_EXIT(&currState, &prevState)
    {
         currState = prevState;
    } BOOST_SCOPE_EXIT_END
    
        3
  •  0
  •   balki    6 年前

    不要使用 std::function .它创建了很多代码,包括vtables。 https://gcc.godbolt.org/z/XgDoHz
    如果您绝对不想使用任何外部类或函数,请执行以下操作:

    bool foo_2() {
        bool f = false;
        auto eos = [&](void*){
            f = true;
        };
        std::unique_ptr<void, decltype(eos)> h{&eos,std::move(eos)};
        return f;
    }
    

    如果您对一个小的可重用函数还满意,那么下面的工作就可以了。这提取了未使用的 void* .

    C++ 14或更高版本

    template<class F>
    auto call_at_end_of_scope(F&& f){
        auto eos = [f{std::forward<F>(f)}](void*){f();};
        return std::unique_ptr<void, decltype(eos)>{&eos,std::move(eos)};
    }
    
    bool foo_3() {
        bool f = false;
        auto handle = call_at_end_of_scope([&](){
            f = true;
        });
        return f;
    }
    
        4
  •  0
  •   R2RT    6 年前

    怎么样 gsl::finally ?图书馆并不是像Boost和 finally 不使用 std::function ,因此可以轻松内联。也没有动态分配 std::unique_ptr

    using namespace std;
    
    void foo(bool & currState, bool newState)
    {
        auto revertState = gsl::finally([prevState = currState, &currState]{
            currState = prevState;
        });
        currState = newState;       
        cout << "currState: " << currState << endl;
    }
    
    
    int main() {
        bool state = false;
        foo(state, true);
        cout << "state: " << state << endl;
        return 0;
    }
    

    在线示例: https://ideone.com/Xi1izz (复制) GSL::终于 ,因为 #include <gsl/gsl> 此处不可用)