离开作用域时调用函数

call function when leaving scope

本文关键字:函数 调用 作用域 离开      更新时间:2023-10-16

离开作用域时自动调用函数的最优雅的解决方案是什么?我目前的方法(见下文)是有效的,但我想应该有一些更通用的东西,如编写一个自定义类。

#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 << "byen"; });
    auto cond = true; // could of course also be false
    if ( cond )
        return;
    return;
}
int main()
{
    foo();
}

当然,可以滥用std::unique_ptr和它的自定义删除器,但由于我在这里并没有真正获取资源,因此在代码可读性方面,这听起来也不太好。有什么建议吗?

Angew和Cassio用ScopeGuard为你指明了正确的方向。使用std::function会导致动态内存分配,并不是最有效的解决方案。基于ScopeGuard的实现通过将要调用的函数对象的类型编码为ScopeGuard类本身的模板参数来避免这种情况。使用辅助函数模板,您不必显式地声明该类型,编译器会为您推断(并且在使用lambda作为要调用的函数对象的情况下必须这样做)。

与其在这里重复所有的细节,我最近写了两篇关于这个领域的文章:

  • 让你的编译器做你的家务
  • OnLeavingScope:续作

第一篇文章的重点是简单性,并从与你最初的问题相似的地方开始,包括一个激励的例子。第二部分将通过所有步骤将其发展为高效且健壮的实现,从而生成简洁且可读性强的代码。第二篇文章还解释了所提供的材料如何与Andrei使用ScopeGuard的工作以及Cassio提到的scope_exit的c++标准建议相关联。

以这种方式使用构造函数/析构函数是解决此排序问题的常用方法。我将它用于锁(构造函数获取锁,析构函数释放锁)和日志目的(构造函数在构造时打印一些东西,析构函数在销毁时打印一些东西,给出一个很好的项目的画法-在后一种情况下,使用宏也将__FILE____LINE__存储在对象中,因此我们可以看到构造函数被调用的位置[几乎不可能对析构函数这样做,但通常可以看到构造函数并确定析构函数被调用的位置。