lambda表達(dá)式是C++11引入的新特性执解,用于聲明一個(gè)函數(shù)帝洪,因?yàn)椴恍枰獙?duì)這個(gè)函數(shù)指定函數(shù)名款青,故lambda表達(dá)式聲明的是匿名函數(shù)。lambda來(lái)源于函數(shù)式編程的概念霍狰,也是現(xiàn)代編程語(yǔ)言的一個(gè)特點(diǎn)抡草。
lambda表達(dá)式具有如下優(yōu)點(diǎn):
(1)聲明式編程風(fēng)格:匿名定義函數(shù),不需要額外命名函數(shù)蔗坯,可以更直接地寫程序康震。
(2)在需要的時(shí)間和地點(diǎn)實(shí)現(xiàn)功能閉包,使編寫程序更加靈活宾濒。因?yàn)槠洳恍枰~外命名函數(shù)腿短,避免了代碼膨脹和功能分散,使得程序更加簡(jiǎn)潔。
lambda表達(dá)式的語(yǔ)法如下:
[caputrue](params)opt -> ret { body; };
(1)caputrue是捕獲列表橘忱。指明了lambda表達(dá)式能訪問(wèn)的外部變量(lambda表達(dá)式函數(shù)體之外的變量)赴魁,以及如何訪問(wèn)這些變量。具體情況如下:
[] 不捕獲任何外部變量
[&] 按引用捕獲钝诚,即捕獲外部作用域中所有變量颖御,并作為引用在函數(shù)體中使用。
[=] 按值捕獲凝颇,即捕獲外部作用域中所有變量潘拱,并作為值副本在函數(shù)體中使用。
[=拧略,&a] 按值捕獲外部作用域中所有變量芦岂,并按引用捕獲a變量。
[b] 按值捕獲b變量垫蛆,同時(shí)不捕獲其他變量禽最。
[this] 應(yīng)用于類中。捕獲當(dāng)前類中的this指針月褥,讓lambda表達(dá)式擁有和當(dāng)前類成員函數(shù)同樣的訪問(wèn)權(quán)限弛随,從而可以在lambda中使用當(dāng)前類的成員函數(shù)和成員變量。如果已經(jīng)在捕獲列表中使用了&或者=宁赤,那么就默認(rèn)添加了該選項(xiàng)舀透。
(2)params是參數(shù)列表。表示傳給lambda表達(dá)式的參數(shù)序列决左,選填愕够。
(3)opt是函數(shù)選項(xiàng)》鹈停可以填mutable惑芭,exception,attribute(選填一個(gè)或者多個(gè))继找。
mutable:說(shuō)明lambda表達(dá)式體內(nèi)的代碼可以修改被捕獲的變量遂跟,如果被捕獲的變量是一個(gè)對(duì)象則可以調(diào)用該對(duì)象的non-const函數(shù)。
exception:說(shuō)明lambda表達(dá)式是否拋出異常婴渡。
attribute:用來(lái)聲明函數(shù)屬性幻锁。
(4)ret是返回類型,選填边臼。
(5)body是函數(shù)體哄尔。
下面以在類中聲明lambda表達(dá)式為例:
class A{
public:
int a = 0;
void fun(int x, int y){
auto a1 = []{ return a; };? ? //error,沒(méi)有捕獲外部變量
auto a2 = [=] { return a + x + y; };? ? //ok
auto a3 = [&] { return a + x + y; };? ? //ok
auto a4 = [this] { return a; };? ? //ok
auto a5 = [this]{return a + x + y; };? /*error柠并,因?yàn)閤岭接,y不是類成員變量富拗,而且沒(méi)有捕獲x,y*/
auto a6 = [this, x, y]{ return a + x + y; };? ? //ok
auto a7 = [this]{ return a ++; };? ? //ok
}
注意事項(xiàng):
1鸣戴、lambda表達(dá)式的延遲調(diào)用啃沪。lambda表達(dá)式按值捕獲外部變量時(shí),在捕獲的瞬間葵擎,外部變量的值就被復(fù)制了谅阿,之后該外部變量值的改變不會(huì)對(duì)之前捕獲到的值有影響。如果希望lambda表達(dá)式在調(diào)用時(shí)即時(shí)訪問(wèn)外部變量酬滤,應(yīng)該使用引用方式捕獲签餐。
int a = 0;
auto func1 = [=] { return a; };
a ++;
std::cout << func1() << std::endl;? ? //輸出0
int b = 0;
auto func2 = [&b]{ return b; };
b ++;
std::cout << func2() << std::endl;? ? //輸出1
2、按值捕獲外部變量時(shí)盯串,在lambda表達(dá)式中修改它們的副本并不會(huì)影響外部的值氯檐,但我們?nèi)匀粺o(wú)法修改這些副本。如果想修改這些副本体捏,需要顯示聲明lambda表達(dá)式為mutable冠摄。lambda表達(dá)式定義的是仿函數(shù)閉包。lambda表達(dá)式捕獲到的任何外部變量几缭,最終均會(huì)變?yōu)殚]包類型的成員變量河泳。按照C++11標(biāo)準(zhǔn),lambda表達(dá)式的operator()默認(rèn)是const的年栓,一個(gè)const成員函數(shù)是無(wú)法修改成員變量的值的拆挥。而mutable就取消了operator()的const。
注:被mutable修飾的lambda表達(dá)式就算沒(méi)有參數(shù)也要顯示寫明參數(shù)列表某抓。
int a = 0;
auto func1 = [=] { return a++; };? ? //error
auto func2 = [=] () mutable { return a++; };? ? //ok