您好,登錄后才能下訂單哦!
這篇文章主要介紹“C++怎么實(shí)現(xiàn)Go的defer功能”,在日常操作中,相信很多人在C++怎么實(shí)現(xiàn)Go的defer功能問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”C++怎么實(shí)現(xiàn)Go的defer功能”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
在Go語(yǔ)言中有一個(gè)關(guān)鍵字:defer,它的作用就是延遲執(zhí)行后面的函數(shù),在資源釋放方面特別有用,比如下面一段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); }
在每一處返回之前都需要調(diào)用fclose來(lái)關(guān)閉文件句柄,中間的流程中斷越多,越是容易遺漏調(diào)用fclose導(dǎo)致未正常關(guān)閉文件。
C++可以使用shared_ptr,auto_ptr之類的智能指針來(lái)管理分配的內(nèi)存,但是像上面這種情況C++并沒(méi)有現(xiàn)成的可使用的代碼來(lái)處理。而Go語(yǔ)言提供了defer關(guān)鍵字來(lái)解決此類問(wèn)題,Go可以按如下方式來(lái)寫(xiě):
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會(huì)自動(dòng)在return之后調(diào)用defer后面的函數(shù)。我們?cè)倏纯聪旅娴氖纠?/p>
package main import ( "fmt" ) func test() (n int, err error) { defer fmt.Println("測(cè)試1") defer fmt.Println("測(cè)試2") defer fmt.Println("測(cè)試3") return fmt.Println("test") } func main() { test() }
它的輸出為:
test
測(cè)試3
測(cè)試2
測(cè)試1
可以看出有多個(gè)defer時(shí),按照先進(jìn)后出的方式執(zhí)行的。
C++中我們可以利用析構(gòu)函數(shù)來(lái)實(shí)現(xiàn),而且C++的局部變量析構(gòu)規(guī)則也是按照先進(jìn)后出的方式執(zhí)行的。為此,我們需要定義一個(gè)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++示例代碼可以寫(xiě)成:
void test() { FILE* fp = fopen("test.txt", "r"); if (nullptr == fp) return; Defer d([&]() { fclose(fp); }); if (...) { return; } if (...) { return; } if (...) { return; } }
不用再在每一處返回前手動(dòng)寫(xiě)代碼關(guān)閉文件了。
但是這里還有一點(diǎn)不便之處就是需要手寫(xiě)一個(gè)lambda表達(dá)式和手動(dòng)定義一個(gè)變量,這個(gè)很好解決,使用宏來(lái)處理。
#define defer1(a,b) a##b #define defer2(a, b) defer1(a, b) #define defer(expr) Defer defer2(__Defer__,__COUNTER__) ([&](){expr;})
為了方便在同一函數(shù)多處使用,定義了defer宏來(lái)給變量命不同的名,前面的代碼可以改為:
void test() { FILE* fp = fopen("test.txt", "r"); if (nullptr == fp) return; defer(fclose(fp)); if (...) { return; } if (...) { return; } if (...) { return; } }
這樣就實(shí)用且方便得多了。下面給出完整代碼以及測(cè)試用例:
#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; }
結(jié)果如下:
以上在VC 2015以及GCC、Clang下測(cè)試通過(guò)。
到此,關(guān)于“C++怎么實(shí)現(xiàn)Go的defer功能”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。