温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++如何实现Go的defer功能

发布时间:2022-03-28 10:13:20 来源:亿速云 阅读:174 作者:iii 栏目:大数据

本篇内容介绍了“C++如何实现Go的defer功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

在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

C++如何实现Go的defer功能

可以看出有多个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
", i, this);
	}
};

int main(int argc, char *argv[])
{
	Test t;
	printf("test:%p
", &t);
	defer(t.f(1));
	defer(t.f(2));
	defer(t.f(3));

	return 0;
}

结果如下:

C++如何实现Go的defer功能

“C++如何实现Go的defer功能”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI