C++實(shí)現(xiàn)Go的defer功能(示例代碼)
在Go語言中有一個關(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來關(guān)閉文件句柄,中間的流程中斷越多,越是容易遺漏調(diào)用fclose導(dǎo)致未正常關(guān)閉文件。
C++可以使用shared_ptr,auto_ptr之類的智能指針來管理分配的內(nèi)存,但是像上面這種情況C++并沒有現(xiàn)成的可使用的代碼來處理。而Go語言提供了defer關(guān)鍵字來解決此類問題,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之后調(diào)用defer后面的函數(shù)。我們再看看下面的示例:
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時,按照先進(jìn)后出的方式執(zhí)行的。
C++中我們可以利用析構(gòu)函數(shù)來實(shí)現(xiàn),而且C++的局部變量析構(gòu)規(guī)則也是按照先進(jìn)后出的方式執(zhí)行的。為此,我們需要定義一個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;
}
}
不用再在每一處返回前手動寫代碼關(guān)閉文件了。
但是這里還有一點(diǎn)不便之處就是需要手寫一個lambda表達(dá)式和手動定義一個變量,這個很好解決,使用宏來處理。
#define defer1(a,b) a##b
#define defer2(a, b) defer1(a, b)
#define defer(expr) Defer defer2(__Defer__,__COUNTER__) ([&](){expr;})
為了方便在同一函數(shù)多處使用,定義了defer宏來給變量命不同的名,前面的代碼可以改為:
void test()
{
FILE* fp = fopen("test.txt", "r");
if (nullptr == fp)
return;
defer(fclose(fp));
if (...)
{
return;
}
if (...)
{
return;
}
if (...)
{
return;
}
}
這樣就實(shí)用且方便得多了。下面給出完整代碼以及測試用例:
#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下測試通過。
到此這篇關(guān)于C++實(shí)現(xiàn)Go的defer功能(示例代碼)的文章就介紹到這了,更多相關(guān)Go關(guān)鍵字defer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV邊緣提取算法流程的實(shí)現(xiàn)(附DEMO)
本文主要介紹了OpenCV邊緣提取算法流程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
C++中vector容器的常用操作方法實(shí)例總結(jié)
vector容器一般被用作創(chuàng)建動態(tài)數(shù)組,動態(tài)數(shù)組就像Python中的list結(jié)構(gòu)一樣,可以比普通數(shù)組擁有更豐富操作方法,下面就為大家整理了一些最常用的操作:2016-05-05
C++?std::copy與memcpy區(qū)別小結(jié)
本文主要介紹了C++?std::copy與memcpy區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
QT的QWebEngineView類知識點(diǎn)詳細(xì)介紹
QWebEngineView是Qt框架中的組件,基于Chromium內(nèi)核,支持HTML5、CSS3、JavaScript等Web技術(shù),適用于嵌入網(wǎng)頁內(nèi)容到Qt應(yīng)用程序,它提供了豐富的接口如加載、導(dǎo)航、與JavaScript交互等,并支持信號槽機(jī)制處理各種網(wǎng)頁事件,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10
C語言動態(tài)內(nèi)存分配函數(shù)的實(shí)現(xiàn)
這篇文章主要介紹了C語言動態(tài)內(nèi)存分配函數(shù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
C++數(shù)據(jù)結(jié)構(gòu)的隊列詳解
這篇文章主要為大家介紹了C++數(shù)據(jù)結(jié)構(gòu)的隊列,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-11-11

