本來說好要聊一聊命名空間的,因為最近在看c++lambda表示式的內容,所以借這個機會我們來好好聊一聊c++的閉包。1.什麼是閉包?
閉包(closure)是函式式程式設計的重要的語法結構。
閉包的概念其實很簡單,一言以蔽之:閉包是帶有上下文的函式。說白了,就是有狀態的函式。也就是說乙個區域性變數n,在被函式物件給「封閉」在函式裡,從而能把值儲存了下來,讓函式能夠儲存狀態。(其實本質上就是乙個類,用純粹物件導向的方式理解,函式也是乙個物件)
扯概念很煩,我們直接上**來看一看。這裡我們用python的**來解釋一下閉包。(後續我們再來詳細聊聊c++之中是怎麼樣實現閉包的):
def getfun(n):
return lambda:n + n
funa = getfun(10)
funb = getfun("abc")
print(funa.func_closure[0].cell_contents)
print(funb.func_closure[0].cell_contents)
列印結果為:
10 //funca的閉包變數
abc //funcb的閉包變數
由上述兩個函式我們看到變數作為一種狀態嵌入到函式由getfun返回的函式之中。不同的語言實現閉包的方式不同。python以函式物件為基礎,為閉包是通過函式物件的屬性來儲存閉包的變數。(這裡在python之中是乙個tuple,從這裡也可以看出,所謂的閉包本質上就是類屬性的乙個語法糖。)
這裡閉包解決了程式設計工作之中的幾個痛點:
閉包的作用有很多,可以在python上實現動態**,如裝飾器等.......這裡就不展開聊閉包的使用,接下來我們要來重點看看在c++之中是如何實現閉包的。
2.c++之中的閉包
c++相對於c的優越點就在於c++能夠支援物件導向的特性,c語言之中在語法層面是不能支援閉包的。我們來看看c++之中有幾種方式來支援閉包特性:
class closure ;
int operator()(int add)
private:
int num;
};int main()
可以看到,過載了()操作符的類closure搖身一變成為了乙個函式,可以直接被呼叫。同時它也包含了物件成員,通過物件成員儲存下來了函式的執行狀態。
int main() ;
cout << clu(50) << endl;
}
使用lambda表示式實現同樣的功能,**就簡潔明瞭許多。這裡的clu是通過乙個匿名類來實現的,所以每個lambda表示式都是獨一無二的,我們只能使用function或auto來捕獲它。這裡lambda表示式通過操作符捕獲外部變數,並且和函式繫結在了一起。
int addnum(int num,int add)
int main()
通過bind函式,將20繫結到對應的引數add之上,而每次呼叫clu函式之時,引數會對應到_1的位置,也就是函式addnum的第乙個引數num。通過bind的函式,我們可以將外部變數與和原函式繫結在了一起,並且生成了乙個新的函式物件。
好的,關於c++之中的閉包就和大家聊到這裡,希望大家在實際coding之中可以用好它........
scala霧中風景 2 小括號與花括號
下面的問題,表面上看是小括號與花括號的問題。map方法這樣寫不能編譯通過 scala list 2 map case 2 ok 換做花括號就可以了 scala list 2 map不了解原因的話,覺得很詭異。分析一下,首先,map方法接受乙個函式,這個函式將list中的元素對映為其他型別。實際上ca...
C 霧中風景10 聊聊左值,純右值與將亡值
1.左值與右值 左值 lvalue 和右值 rvalue 是c 型別系統之中的基礎概念,我們不需要了解這些基礎概念,同樣也能寫出 但是如果沒有弄清左右值的概念,對於許多c 高階特性的探索會一葉障目,所以筆者嘗試總結一下自己對於左值與右值的理解。在c 11之前的版本,基本沿用了c語言之中對於左值與右值...
ruby學習筆記 7 閉包
閉包的乙個重要特徵是 過程 方法 內部定義的變數,即使在方法呼叫完成以後,仍然可以繼續引用到!即延長了生命週期 defmethod n puts n 測試用 returnproc 關鍵 proc是乙個過程物件,只能由 委託 用call來呼叫,這裡在過程內部引用了引數變數n,將會在多次call該過程後...