UE 中有一个宏ON_SCOPE_EXIT
,它的用法为:
1 | // Make sure module info is added to known modules and proper delegates are fired on exit. |
在 UE4 Modules:Find the DLL and load it 里曾提到过这种用法:
这段代码的意思是在退出当前的作用域 (Scope) 时执行
{}
中的逻辑,简单地来说,它定义了一个当前作用域的对象并托管了一个 Lambda,在离开当前作用域的时候通过 C++ 的 RAII 机制来调用托管的 Lambda.
今天来简单分析一下它的实现。
首先,ON_SCOPE_EXIT
的宏定义为:
1 |
由此展开,最开始的那个使用的宏就等价替换为:
1 | const auto ANONYMOUS_VARIABLE(ScopeGuard_) = ::ScopeExitSupport::FScopeGuardSyntaxSupport() + [&](){ |
通常 lambda 用在谓词和调用的时候还好理解,但是这个搞了个 +
有点不走寻常路,由此可以推断类型 ::ScopeExitSupport::FScopeGuardSyntaxSupport
必然重载了 operator+
操作符,并且是个模板函数。
查看 ::ScopeExitSupport::FScopeGuardSyntaxSupport
的代码:
1 | // Runtime\Core\Public\Misc\ScopeExit.h |
果然!类型 FScopeGuardSyntaxSupport
通过模板重载了 operator+
,它要求接收一个重载了operator()
的泛型 ** 函数对象 (functional object)** 类型,据此产生一个TScopeGuard
的类型,并将传递进来的函数对象托管,在这个 TScopeGuard
的对象的析构函数中 (destructor) 调用了托管的函数对象。
其中隐藏的关键是通过 ::ScopeExitSupport::FScopeGuardSyntaxSupport() + [&](){}
得到的 TScopeGuard
的对象是个 ** 局部对象 (automattic storage duration)**,只存在于当前的作用域(Scope) 中,在离开当前作用域时会自动销毁(调用析构函数),离开作用域时局部变量的销毁顺序为按定义的逆序执行。
[ISO/IEC 14882:2014 § 6.6]On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction.