分享
  1. 首页
  2. 文章

C++11实现golang的defer类似Java finally操作。

eclipser1987 · · 2522 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

// Copyright 2013 <chaishushan#gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef _DEFER_H_
#define _DEFER_H_
#include <functional>
#include <iostream>
//
// 需要支持C11 -std=c++11
// defer 语句定义一个延迟执行闭包函数的对象
//
// 基于用法:
//
// FILE* fp = fopen("foo.txt", "rt");
// if(fp == NULL) return false;
// defer([&](){ printf("fclose(fp)\n"); fclose(fp); });
// 
// char* buf = new char[1024];
// defer([&](){ printf("delete buf\n"); delete[] buf; });
// 
// defer([](){ printf("defer a: %d\n", __LINE__); });
// defer([](){ printf("defer a: %d\n", __LINE__); });
// defer([](){ printf("defer a: %d\n", __LINE__); });
// 
// {
// defer([](){ printf("defer b: %d\n", __LINE__); });
// defer([](){ printf("defer b: %d\n", __LINE__); });
// defer([](){ printf("defer b: %d\n", __LINE__); });
// }
// 
// defer([](){
// printf("defer c:\n");
// for(int i = 0; i < 3; ++i) {
// defer([&](){ defer([&](){
// printf("\ti = %d: begin\n", i);
// defer([&](){ printf("\ti = %d\n", i); });
// printf("\ti = %d: end\n", i);
// });});
// }
// });
//
// 注意事项:
//
// 1. defer 定义的对象在超出作用域时执行闭包函数(析构函数)
// 2. defer 定义的对象在同一个文件内部标识符不同(根据行号生成)
// 3. defer 在全局作用域使用可能会出现重名现象(行号相同)
// 4. defer 在判断语句使用可能提前执行(作用域结束时)
// 5. defer 在循环语句内使用无效(作用域结束时)
// 6. defer 和Go语言的defer并不完全等价
//
// 更多参考:
//
// http://blog.korfuri.fr/post/go-defer-in-cpp/
// http://blog.korfuri.fr/attachments/go-defer-in-cpp/defer.hh
// http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
// http://golang.org/doc/effective_go.html#defer
// http://golang.org/ref/spec#Defer_statements
//
#define defer _DEFER_ACTION_MAKE /* ([&](){ ... }); */
// auto _defer_action_line???_ = _DeferredActionCtor([&](){ ... })
#define _DEFER_ACTION_MAKE auto \
 _DEFER_ACTION_VAR(_defer_action_line, __LINE__, _) = _DeferredActionCtor
#define _DEFER_ACTION_VAR(a, b, c) _DEFER_TOKEN_CONNECT(a, b, c)
#define _DEFER_TOKEN_CONNECT(a, b, c) a ## b ## c
// 持有闭包函数
class _DeferredAction {
private:
 std::function<void()> func_;
 template<typename T>
 friend _DeferredAction _DeferredActionCtor(T&& p);
 template<typename T>
 _DeferredAction(T&& p): func_(std::bind(std::forward<T>(p))) {
 std::cout << "NEW 1" << std::endl;
 }
 _DeferredAction();
 _DeferredAction(_DeferredAction const&);
 _DeferredAction& operator=(_DeferredAction const&);
 _DeferredAction& operator=(_DeferredAction&&);
public:
 _DeferredAction(_DeferredAction&& other):
 func_(std::forward<std::function<void()>>(other.func_)) {
 other.func_ = nullptr;
 std::cout << "NEW 2" << std::endl;
 }
 ~_DeferredAction() {
 if(func_) { func_(); }
 std::cout << "DELETE" << std::endl;
 }
};
template<typename T>
_DeferredAction _DeferredActionCtor(T&& p) {
 return _DeferredAction(std::forward<T>(p));
}
#endif // _DEFER_H_



测试:


/* 
 * File: main.cpp
 * Author: Vicky.H
 * Email: eclipser@163.com
 */
#include "defer.h"
#include <iostream>
void sayHello(const char* name) {
 printf("hello %s\n", name);
}
void funTest() {
 printf("funTest 1\n");
 defer([]() {
 printf("defer c: %d\n", __LINE__); });
 defer([]() {
 printf("defer c: %d\n", __LINE__); });
 defer([]() {
 printf("defer c: %d\n", __LINE__); });
 printf("funTest 2\n");
}
/*
 * 
 */
int main(void) {
 defer([]() {
 printf("defer a: %d\n", __LINE__); });
 defer([]() {
 printf("defer a: %d\n", __LINE__); });
 defer([]() {
 printf("defer a: %d\n", __LINE__); });
 defer([](){
 sayHello("jack"); });
 {
 defer([](){ printf("defer b: %d\n", __LINE__); });
 defer([](){ printf("defer b: %d\n", __LINE__); });
 defer([](){ printf("defer b: %d\n", __LINE__); });
 std::cout << "in code scope" << std::endl;
 }
 
 std::cout << "\n---------------------------" << std::endl;
 
 std::cout << "Done 1" << std::endl;
 std::cout << "Done 2" << std::endl;
 std::cout << "Done 3" << std::endl;
 
 // throw "exception happen";
 
 std::cout << "\n---------------------------" << std::endl;
 
 funTest();
 return 0;
}


git: http://git.oschina.net/eclipser/defer4cpp.git


注意,以上代码需要支持C++11 : -std=c++11


输出:

NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
in code scope
defer b: 42
DELETE
defer b: 41
DELETE
defer b: 40
DELETE


---------------------------
Done 1
Done 2
Done 3


---------------------------
funTest 1
NEW 1
NEW 1
NEW 1
funTest 2
defer c: 22
DELETE
defer c: 20
DELETE
defer c: 18
DELETE
hello jack
DELETE
defer a: 35
DELETE
defer a: 33
DELETE
defer a: 31
DELETE


运行 FINISHED; 退出值0; 实时: 20ms; 用户: 0ms; 系统: 0ms



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:eclipser1987

查看原文:C++11实现golang的defer类似Java finally操作。

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2522 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏