欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實(shí)現(xiàn)defer聲明方法詳解

 更新時(shí)間:2022年11月16日 11:43:21   作者:程序員~彭國慶  
這篇文章主要介紹了C++實(shí)現(xiàn)defer聲明,在和朋友交談時(shí)候,無意間了解到Go語言的defer,發(fā)現(xiàn)挺有意思的。和智能指針類似,當(dāng)出了作用域后,被defer修飾的操作才會(huì)執(zhí)行

本文代碼地址:https://github.com/pengguoqing/samples_code

一、前言

   在Go 語言里面有一個(gè) defer 聲明, 它的作用是將函數(shù)調(diào)用保存在列表中, 函數(shù)返回時(shí)依次調(diào)用列表中的函數(shù)。

之前實(shí)現(xiàn)簡(jiǎn)易版的智能指針文章中指出, 智能指針內(nèi)部就是利用的 RAII特點(diǎn), 將對(duì)象的聲明周期使用棧來管理。 因此可以借鑒 Go語言中的 defer邏輯, 然后結(jié)合RAII的特點(diǎn)來實(shí)現(xiàn)一個(gè) C++ 版本的 defer, 依次來實(shí)現(xiàn)在當(dāng)前作用域內(nèi)必須要調(diào)用的函數(shù)。

  關(guān)于離開作用域時(shí)某些函數(shù)必須調(diào)用的一個(gè)經(jīng)典例子就是文件的關(guān)閉, 如下:

	FILE *file = fopen("readme.ext", "rb");
	if (file == NULL) 
	{
		return;
	}
	if (caseOne)
	 {
		// dosomething
		fclose(file); // 必須手動(dòng)關(guān)閉文件
		return;
	}
	//caseTwo
	//dosomething
	fclose(file);     // 必須手動(dòng)關(guān)閉文件
	return;

   這種情況下需要顯示的在多個(gè) return 的之前調(diào)用 fclose(file)關(guān)閉文件, 一方面維護(hù)的時(shí)候可能會(huì)忘記關(guān)閉文件, 而且代碼看起來也不夠簡(jiǎn)潔。熟悉 RAII 技術(shù)后, 常用的方式是實(shí)現(xiàn)一個(gè)相關(guān) scope 類封裝, 在文件開發(fā)成功后將 FILE 句柄傳入構(gòu)造函數(shù),在離開作用域時(shí)利用棧資源銷毀調(diào)用 scope 類的析構(gòu)函數(shù) 關(guān)閉文件。這當(dāng)前時(shí)一種解決方案, 但是每當(dāng)遇到一個(gè)這種場(chǎng)景時(shí)就需要手動(dòng)封裝一個(gè)相關(guān)的 scope 類。所以需要一個(gè) 類似 defer的東西方便使用。

二、實(shí)現(xiàn)

2.1 相關(guān)技術(shù)

①編譯器類型自動(dòng)推導(dǎo);

②Lambda表達(dá)式(仿函數(shù));

③RAII;

④轉(zhuǎn)發(fā)引用

2.2 實(shí)現(xiàn)

  對(duì)函數(shù)調(diào)用只需要一次, 所以需要類似 unique_ptr的方式, 管理仿函數(shù)對(duì)象的類只能被移動(dòng), 不能被拷貝和賦值,聲明如下:

public:
	inline CXDeferImpl(const Functor& functor);
	inline CXDeferImpl(Functor&& functor);
	inline CXDeferImpl(CXDeferImpl&& another);
	inline ~CXDeferImpl();
private:
	//不允許拷貝, 賦值
	CXDeferImpl(const CXDeferImpl& another)			  = delete;
	CXDeferImpl operator=(const CXDeferImpl& another) = delete;
	CXDeferImpl operator=(CXDeferImpl&& another)	  = delete;

類成員只需要一個(gè)仿函數(shù)對(duì)象和一個(gè)是否有效的標(biāo)志:

private:
    Functor  m_func;
    bool     m_valid;

2.3 對(duì)外接口

  以宏的方式對(duì)外提供調(diào)用, 利用 Lambda表達(dá)式封裝需要調(diào)用的函數(shù),畢竟它的內(nèi)部就是一個(gè)實(shí)現(xiàn)仿函數(shù)的類, 再讓編譯器自動(dòng)推導(dǎo) Lambda 類型來構(gòu)造一個(gè) CXDeferImpl實(shí)例, 每次 defer() 聲明都創(chuàng)建一個(gè)對(duì)象 CXDeferImpl。

#define CONCAT_(a, b, c) a##b##c
#define CONCAT(a, b, c)  CONCAT_(a, b, c)
#define defer(x) \
  auto CONCAT(defer_, __LINE__, __COUNTER__) = MakeDeferIns([&]{x;})

三、測(cè)試

  當(dāng)然是是用萬能并且經(jīng)典的 “Hello world!” 了, 哈哈哈。測(cè)試其離開作用域時(shí)能不能完整的輸出的 “Hello world!”, 代碼如下:

void TestDefer()
{
  defer(cout<<"world!"<<endl);
  cout<<"Hello ";
}
void TestDefer2()
{
  {
      defer(TestDefer());
      cout<<"Test defer in scope"<<endl;
  }
  cout << "Test defer are ok?" << endl;
  defer(cout<<"TestDefer2"<<endl);
}
void TestDefer3(int a)
{
  {
      defer(cout << "test param func " << a << endl);
  }
  defer(cout << "TestDefer3" << endl);
}
int main()
{
  TestDefer2();
  TestDefer3(100);

  return 0;
}

輸出如下:

到此這篇關(guān)于C++實(shí)現(xiàn)defer聲明方法詳解的文章就介紹到這了,更多相關(guān)C++ defer內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論