您好,登錄后才能下訂單哦!
本篇內容介紹了“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
可以看出有多個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; }
結果如下:
以上在VC 2015以及GCC、Clang下測試通過。
“C++中如何實現Go的defer功能”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。