【问题标题】:Is there a class/template in std library to perform a task when out of scope?标准库中是否有类/模板可以在超出范围时执行任务?
【发布时间】:2017-03-30 07:28:13
【问题描述】:

我们有一些资源,需要手动释放。除了显式编写 RAII 包装器来管理其资源外,std 库中是否有任何内置模板或类来自动执行 lambda 任务?

{
    auto resource = InitResource();        
    GuardedTask task ([&resource]{ FreeUp(resource); }); // Simply bind a clean up lambda
    ...
    if(failed_condition_met) { return false; } // Free up
    ...
    if(another_failed_condition_met) { return false; } // Free up

} // Free up

该类的行为可能如下所示,但我想知道轮子可能已经内置在 std 库中,或者我应该编写自己的。

struct GuardedTask
{
    std::function<void()> task;
    GuardedTask(std::function<void()> f): task(f) {}
    ~GuardedTask(){ task(); }
};

【问题讨论】:

  • 请注意,您必须删除复制构造函数/赋值。

标签: c++ c++11


【解决方案1】:

这种模式称为范围保护,除了 RAII 清理之外还有许多其他用途,例如事务安全功能。不幸的是,没有标准化的范围保护,但有提议 P0052 打算实现这一点。

【讨论】:

    【解决方案2】:

    您可以在 std::unique_ptr 上使用自定义删除器。

    参见this question

    【讨论】:

    • 带有自定义删除器的 unique_ptr 很好。但它对于一种单一资源很有用,我需要注意 unique_ptr 中的 T 和 Deleter 类型。有时我想要一个“清理任务”来负责这个一次性范围,只需传递一个 lambda。
    • 嗯,我认为没有一种概念上干净的方法可以做到这一点。我不知道你是否写过 C,但关键是,即使你为一个函数编写了单个退出点,函数的不同退出状态也需要以不同的方式处理。因此,在 C++ 中,您通常应该确保资源在创建后自动处理。如果你有一个函数来释放很多东西,其中一些可能没有被初始化(例如,如果一个构造函数抛出),这可能会导致你的退出块中出现意外的失败,或者导致复杂的逻辑。
    猜你喜欢
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多