iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >C++实现Go的defer功能(示例代码)
  • 638
分享到

C++实现Go的defer功能(示例代码)

c+GOdefer示例C++ 2022-06-07 20:06:44 638人浏览 独家记忆
摘要

在Go语言中有一个关键字:defer,它的作用就是延迟执行后面的函数,在资源释放方面特别有用,比如下面一段C/C++的示例代码: void test() { FILE* fp

Go语言中有一个关键字:defer,它的作用就是延迟执行后面的函数,在资源释放方面特别有用,比如下面一段C/C++的示例代码:


void test()
{
FILE* fp = fopen("test.txt", "r");
if (nullptr == fp)
return;
if (...)
{
fclose(fp);
return;
}
if (...)
{
fclose(fp);
return;
}
if (...)
{
fclose(fp);
return;
}
fclose(fp);
}

在每一处返回之前都需要调用fclose来关闭文件句柄,中间的流程中断越多,越是容易遗漏调用fclose导致未正常关闭文件。

c++可以使用shared_ptr,auto_ptr之类的智能指针来管理分配的内存,但是像上面这种情况C++并没有现成的可使用的代码来处理。而Go语言提供了defer关键字来解决此类问题,Go可以按如下方式来写:


func test() {
file, err := os.Open("test.txt")
if err != nil {
return
}
defer file.Close()
if ... {
return
}
if ... {
return
}
if ... {
return
}
}

只需要使用一句:


defer file.Close()

即可,Go会自动在return之后调用defer后面的函数。我们再看看下面的示例:


package main
import (
"fmt"
)
func test() (n int, err error) {
defer fmt.Println("测试1")
defer fmt.Println("测试2")
defer fmt.Println("测试3")
return fmt.Println("test")
}
func main() {
test()
}

它的输出为:

test
测试3
测试2
测试1

可以看出有多个defer时,按照先进后出的方式执行的。

C++中我们可以利用析构函数来实现,而且C++的局部变量析构规则也是按照先进后出的方式执行的。为此,我们需要定义一个Defer类:


#include <functional>
typedef std::function<void()> fnDefer;
class Defer
{
public:
Defer(fnDefer fn) : m_fn(fn)
{
}
~Defer()
{
if(m_fn)
m_fn();
}
private:
fnDefer m_fn;
};

这样,前面的C++示例代码可以写成:


void test()
{
FILE* fp = fopen("test.txt", "r");
if (nullptr == fp)
return;
Defer d([&]()
{
fclose(fp);
});
if (...)
{
return;
}
if (...)
{
return;
}
if (...)
{
return;
}
}

不用再在每一处返回前手动写代码关闭文件了。

但是这里还有一点不便之处就是需要手写一个lambda表达式和手动定义一个变量,这个很好解决,使用宏来处理。


#define defer1(a,b) a##b
#define defer2(a, b) defer1(a, b)
#define defer(expr) Defer defer2(__Defer__,__COUNTER__) ([&](){expr;})

为了方便在同一函数多处使用,定义了defer宏来给变量命不同的名,前面的代码可以改为:


void test()
{
FILE* fp = fopen("test.txt", "r");
if (nullptr == fp)
return;
defer(fclose(fp));
if (...)
{
return;
}
if (...)
{
return;
}
if (...)
{
return;
}
}

这样就实用且方便得多了。下面给出完整代码以及测试用例:


#include <functional>
using namespace std;
typedef std::function<void()> fnDefer;
class Defer
{
public:
Defer(fnDefer fn) : m_fn(fn)
{
}
~Defer()
{
if(m_fn)
m_fn();
}
private:
fnDefer m_fn;
};
#define defer1(a,b) a##b
#define defer2(a, b) defer1(a, b)
#define defer(expr) Defer defer2(__Defer__,__COUNTER__) ([&](){expr;})
class Test
{
public:
void f(int i)
{
printf("f:%d %p\n", i, this);
}
};
int main(int arGC, char *argv[])
{
Test t;
printf("test:%p\n", &t);
defer(t.f(1));
defer(t.f(2));
defer(t.f(3));
return 0;
}

结果如下:

以上在VC 2015以及GCC、Clang下测试通过。

到此这篇关于C++实现Go的defer功能(示例代码)的文章就介绍到这了,更多相关Go关键字defer内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


您可能感兴趣的文档:

--结束END--

本文标题: C++实现Go的defer功能(示例代码)

本文链接: https://www.lsjlt.com/news/30650.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作