在 C++11(或更新版本)中创建 RAII 包装器而无需编写新的 class 的最短路径是什么?

What's the shortest path in C++11 (or newer) to create an RAII wrapper without having to write a new class?

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

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

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 工作并在销毁时调用自定义析构函数。

有没有更简洁的方法来做到这一点,而不必写一个完整的 class,并摆脱虚拟 intnew

您可以使用BOOST_SCOPE_EXIT

auto prevState{currState};
currState = newState;
BOOST_SCOPE_EXIT(&currState, &prevState)
{
     currState = prevState;
} BOOST_SCOPE_EXIT_END

比你的好一点点:你可以在自定义析构函数中使用&prevState而不删除它,所以你不需要newdelete一些东西:

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;
}

您还忘记在 lambda 中捕获 currState

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

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

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;
}

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::finally,因为#include <gsl/gsl>在这里不可用)