【发布时间】:2015-10-10 05:23:17
【问题描述】:
我正在阅读有关 go 语言的 defer 声明。它允许您指定函数结束时要执行的操作。例如,如果你有一个文件指针或资源,而不是用每个可能的返回路径写 free/delete,你只需要指定一次 defer 函数。
看起来类似的东西最终可能会出现在 C++ 中(What is standard defer/finalizer implementation in C++?,Will there be standardization of scope guard/scope exit idioms?)在此之前,使用析构函数进行回调的对象有什么不可预见的事情吗?它看起来像 destructor order for local variables is sane 并且它也能很好地处理异常,尽管可能不会退出信号。
这是一个示例实现...有什么问题吗?
#include <iostream>
#include <functional>
using namespace std;
class FrameExitTask {
std::function<void()> func_;
public:
FrameExitTask(std::function<void()> func) :
func_(func) {
}
~FrameExitTask() {
func_();
}
FrameExitTask& operator=(const FrameExitTask&) = delete;
FrameExitTask(const FrameExitTask&) = delete;
};
int main() {
FrameExitTask outer_task([](){cout << "world!";});
FrameExitTask inner_task([](){cout << "Hello, ";});
if (1+1 == 2)
return -1;
FrameExitTask skipped_task([](){cout << "Blam";});
}
输出:Hello, world!
【问题讨论】:
-
这可能更适合CodeReview。请注意,已经有很多类似 ScopeGuard 的类的实现,那么为什么要重新发明轮子呢?我知道的一些实现有各种好处或专用工具,我更喜欢你的版本(例如,没有类型擦除)。
-
这个问题是每个类都应该已经完成了你在它们的析构函数中所做的事情,因此 C++ 中的用例比 Go 中的用例少得多。如果您正在寻找现有的实现,请检查 boost.ScopeExit。我认为 Facebook 的 Folly 也有一个。
-
你最好标记析构函数
noexcept。如果您使用FrameExitTask的函数正常返回,您的finally 处理程序中的异常可能会起作用。如果函数由于其他异常而退出,那么您的处理程序的第二个异常将导致问题。 -
FrameExitTask的析构函数隐式为noexcept。也就是说,如果func_()抛出异常,你的程序将被终止。 -
跟
functional-programming标签有什么关系?
标签: c++ c++11 go functional-programming destructor