C++11的新特性lambda的小试牛刀RAII
C/C++的资源是手动管理的
这导致程序员在申请资源时,最后用完了偶尔会忘记回收
C++语言的发明者倡导RAII,资源获取即初始化
使用对象来管理资源的生命周期,在超出作用域时,析构函数自动释放资源
然而,很多程序员不愿意每次使用一个资源,就生成一个class类型来管理资源
C++ 11的来临,可以很优雅的解决这个麻烦
用到std function和lambda闭包
1 class ScopeGuard 2 { 3 public: 4 explicit ScopeGuard(std::function<void()> onExitScope) 5 : onExitScope_(onExitScope), dismissed_(false) 6 { } 7 8 ~ScopeGuard() 9 { 10 if(!dismissed_) 11 { 12 onExitScope_(); 13 } 14 } 15 16 void Dismiss() 17 { 18 dismissed_ = true; 19 } 20 21 private: 22 std::function<void()> onExitScope_; 23 bool dismissed_; 24 25 private: // noncopyable 26 ScopeGuard(ScopeGuard const&); 27 ScopeGuard& operator=(ScopeGuard const&); 28 }; 29 30 HANDLE h = CreateFile(...); 31 ScopeGuard onExit([&] { CloseHandle(h); });
资源申请和释放放在邻近的地方,配对使用,简单明了
唯一的不足就是每次都需要声明一个onExit,如果有多个资源需要释放,则需要声明多个,从而带来名字的烦恼
为了更加的简洁和优雅,让宏来帮我们
1 #define SCOPEGUARD_LINENAME_CAT(name, line) name##line 2 #define SCOPEGUARD_LINENAME(name, line) SCOPEGUARD_LINENAME_CAT(name, line) 3 #define ON_SCOPE_EXIT(callback) ScopeGuard SCOPEGUARD_LINENAME(EXIT, __LINE__)(callback) 4 5 /*Usage: */ 6 7 /* Acquire Resource 1 */ 8 ON_SCOPE_EXIT( [&] { /* Release Resource 1 */ }) 9 10 /* Acquire Resource 2 */ 11 ON_SCOPE_EXIT( [&] { /* Release Resource 2 */ })
资源的申请和释放放在邻近的地方,可读性非常强
让编译器帮我们解决名字重名的担忧,代码简单易懂