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 */ })

资源的申请和释放放在邻近的地方,可读性非常强
让编译器帮我们解决名字重名的担忧,代码简单易懂