纠错
前一篇《如何在C++中延迟执行》有一点疏忽,会导致在某些不正确使用的情况下发生崩溃。需将defer类更改如下:
class defer{ using OnDestructorAction = std::function;public: defer(defer&) = delete; defer(OnDestructorAction action) : OnDestructor(action) {} ~defer() { if (OnDestructor) { OnDestructor(); } } defer operator=(defer&) = delete; void* operator new(size_t) = delete;protected: OnDestructorAction OnDestructor;};
这是由于可能会被有意或无意这样使用
defer clean(nullptr);
将导致运行时错误。
优化
要说和Golang的defer相比,前面版本已经接近,只是不可以像Golang一样作为关键字和延时执行某一语句,如:
defer file.close()
但是由于是自定义的,就会有更高的可控性和灵活性。这里将对defer类做一点优化,以减少在一个函数中可能存在的多个defer对象。例如《如何在C++中延迟执行》中的最后的示例,为了在不同阶段执行清理,创建了2个defer对象。解决方法也很简单,让一个defer对象可以容纳多个清理方法就可以了。更改后的示例版本如下
#include #include #include class defer{ using OnDestructorAction = std::function;public: defer(defer&) = delete; defer(OnDestructorAction action) { OnDestructor.push(action); } ~defer() { while (OnDestructor.size() > 0) { auto action = OnDestructor.top(); OnDestructor.pop(); if (action) { action(); } } } void Append(OnDestructorAction action) { OnDestructor.push(action); } defer operator=(defer&) = delete; void* operator new(size_t) = delete;protected: std::stack OnDestructor;};void fun(bool doit){ defer clean([]() { std::cout << "clean" << std::endl; }); if (!doit) { std::cout << "! doit" << std::endl; return; } clean.Append([]() { std::cout << "clean 2" << std::endl; }); std::cout << "doit" << std::endl; return;}int main(){ std::cout << "fun(false)" << std::endl; fun(false); std::cout << "func(true)" << std::endl; fun(true); return 0;}
执行程序,得到输出如下
fun(false)! doitcleanfunc(true)doitclean 2clean
没有什么特别的,只是将OnDestructor成员更改为使用容器存放多个OnDestructorAction对象。唯一需要注意的是,这里窗口选择的是stack。为什么要选择stack呢?思考一下吧!
原创文章,转载请保留出处 https://www.toutiao.com/i6895175707958346248/