离开作用域时调用函数

5

在离开作用域时自动调用函数的最优雅解决方案是什么? 我的当前方法(见下文)可以工作,但我猜应该有更通用的方法,例如编写一个自定义类来实现。

#include <iostream>
#include <functional>

using namespace std;

class DoInDtor
{
public:
    typedef function<void()> F;
    DoInDtor(F f) : f_(f) {};
    ~DoInDtor() { f_(); }
private:
    F f_;
};

void foo()
{
    DoInDtor byeSayerCustom([](){ cout << "bye\n"; });

    auto cond = true; // could of course also be false
    if ( cond )
        return;

    return;
}

int main()
{
    foo();
}

当然,一个人可以滥用std::unique_ptr及其自定义删除器,但由于我并没有真正获取资源,因此从代码可读性的角度来看,这对我来说也不是很好。 有什么建议吗?


这可能适合放在代码审查上。 - Kerrek SB
离开函数还是离开作用域?因为这是两件不同的事情。虽然这并不是很重要,但在每个作用域中放置DoInDtor对象听起来很费力。你想要实现什么目标? - Kiril Kirov
2
顺便提一下,如果离开作用域时要调用的函数可能会抛出异常,通常不应这样做! - anderas
1
你可能想要查看Loki库中的ScopeGuard类。(Loki's) (ScopeGuard) - Angew is no longer proud of SO
1
将来,我们可能会得到这个:标准库的作用域资源 - 通用RAII包装器 - Cassio Neri
显示剩余5条评论
2个回答

3
Angew和Cassio在这里向您指出了ScopeGuard的正确方向。使用std::function可能会导致动态内存分配,不是最有效的解决方案。基于ScopeGuard的实现通过将要调用的函数对象的类型编码到ScopeGuard类本身中作为模板参数来避免这种情况。借助一个辅助函数模板,您永远不必显式地声明该类型,编译器会为您推断它(并且在使用lambda作为要调用的函数对象的情况下必须这样做)。
与其在此重复所有细节,我最近写了两篇关于这个非常领域的文章: 第一篇文章注重简洁,并从与您的原始问题类似的位置开始,包括一个激励性的例子。第二篇文章通过所有步骤来演变成一个高效和强大的实现,这导致了简明易读的代码。第二篇文章还解释了所呈现材料与Andrei在ScopeGuard方面的工作以及C++标准提案有何关系,这些提案由Cassio提到的scope_exit提出。

2
在IT技术中,使用构造函数/析构函数的方式是解决问题的常用方法。我既在锁定(构造函数获取锁,析构函数释放锁),也在日志记录(构造函数在构建时打印一些内容,析构函数在销毁时打印内容,可以很好地呈现项目的调用图 - 在后一种情况下,使用宏来存储__FILE__和__LINE__,以便我们可以看到构造函数被调用的位置[对于析构函数几乎不可能做到这一点,但通常可以看到构造函数并找出析构函数被调用的位置]).

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接