C++11:lambda表達(dá)式

1舵揭、介紹

lambda表達(dá)式常用于向函數(shù)傳遞謂詞药磺,有些函數(shù)的參數(shù)只能接受一元謂詞(如find_if)辅柴,但是如果我們需要向函數(shù)傳遞二元謂詞,這時(shí)候可以使用lambda表達(dá)式(匿名函數(shù))怠噪,lambda表達(dá)式是重載了運(yùn)算符[]的函數(shù)恐似。

2、lambda表達(dá)式的使用

一個(gè)lambda表達(dá)式表示一個(gè)可調(diào)用的代碼單元傍念,我們可以將其理解為一個(gè)未命名的內(nèi)聯(lián)函數(shù)矫夷。與函數(shù)相似,一個(gè)lambda表達(dá)式具有一個(gè)返回類(lèi)型憋槐、一個(gè)參數(shù)列表和一個(gè)函數(shù)體双藕。一個(gè)lambda表達(dá)式具有如下的形式:

[捕獲參數(shù)](參數(shù)列表) -> 返回類(lèi)型 {函數(shù)體}

lambda表達(dá)式必須使用尾置返回類(lèi)型。

(1)簡(jiǎn)單的lambda表達(dá)式

auto func = [] {return 42;};

上式中忽略了參數(shù)列表和返回類(lèi)型阳仔,但是必須包含捕獲列表和函數(shù)體忧陪。

cout <<func() <<endl; //調(diào)用func的方式和普通函數(shù)類(lèi)似,此式輸出42.

(2)含有參數(shù)的lambda表達(dá)式

向lambda表達(dá)式傳遞參數(shù)的時(shí)候驳概,和普通函數(shù)類(lèi)似赤嚼,但是lambda表達(dá)式不能含有默認(rèn)值旷赖,因此傳遞參數(shù)的時(shí)候?qū)崊⑴c形參一定相等顺又。
完成isShorter函數(shù)的lambda表達(dá)式如下:

[] (const string& a, const string& b) { return a.size() < b.size(); }

空捕獲列表表示lambda表達(dá)式不使用其所在函數(shù)的局部變量。上述的lambda表達(dá)式調(diào)用的時(shí)候會(huì)進(jìn)行比較兩個(gè)參數(shù)的長(zhǎng)短等孵,并返回bool值稚照。

在stable_sort()函數(shù)中使用上述的lambda表達(dá)式:

stable_sort(words.begin(), words.end(), [] (const string& a, const string& b) { return a.size() < b.size(); });

這樣stable_sort函數(shù)在排序的時(shí)候就會(huì)調(diào)用lambda表達(dá)式,按字符串長(zhǎng)度從小到大排列俯萌。

注:一個(gè)lambda表達(dá)式如果如果忽略返回類(lèi)型果录,那么lambda表達(dá)式會(huì)根據(jù)函數(shù)體的返回值推斷類(lèi)型,但是前提是函數(shù)體只有一個(gè)return語(yǔ)句咐熙;如果lambda表達(dá)式忽略了返回類(lèi)型弱恒,并且函數(shù)體不有return語(yǔ)句之外的語(yǔ)句,那么返回類(lèi)型是void棋恼。

(3)使用捕獲列表的lambda表達(dá)式

lambda表示一般是用于函數(shù)中返弹,如果lambda表達(dá)式需要使用到函數(shù)中的局部變量,則需要是用捕獲列表進(jìn)行捕獲爪飘。
如:使用find_if函數(shù)查找第一個(gè)滿足字符串長(zhǎng)度大于len的字符义起。

int len = 5;
stable_sort(words.begin(), words.end(), [] (const string& a, const string& b) { return a.size() < b.size(); });
find_if(words.begin(), words.end(), [len](const string& a) { return a.size() > len; });

上述例子中find_if函數(shù)中的第三個(gè)參數(shù)傳遞了一個(gè)lambda表達(dá)式,該表達(dá)式使用捕獲列表捕獲了參數(shù)len师崎,對(duì)words中的每一個(gè)元素的長(zhǎng)度和len進(jìn)行比較默终,返回第一個(gè)長(zhǎng)度大于len的字符串的迭代器。

(4)值捕獲與引用捕獲

值捕獲:

lambda表達(dá)式采用[name]的形式捕獲參數(shù)的時(shí)候,便是使用的值捕獲齐蔽。采用值捕獲的前提是參數(shù)能夠拷貝两疚。與函數(shù)參數(shù)不同,被捕獲的變量的值是在lambda表達(dá)式創(chuàng)建的時(shí)候拷貝的肴熏,而不是調(diào)用時(shí)拷貝鬼雀。

int i = 40;
auto func = [i] {return i;};
i = 0;
auto j = func();  //此時(shí)變量j=40,func保存了我們創(chuàng)建它時(shí)i的拷貝
引用捕獲:

引用捕獲和變量的引用類(lèi)似蛙吏,在lambda表達(dá)式中采用引用捕獲源哩,那么在lambda表達(dá)式使用的便是引用所綁定的對(duì)象的值。如果采用引用捕獲鸦做,我們必須確保被引用的對(duì)象在lambda表達(dá)式執(zhí)行的時(shí)候是存在的励烦。

int i = 40;
auto func = [&i] {return i;};
i = 0;
auto j = func();  //此時(shí)變量j=0,func保存的是i的引用泼诱,沒(méi)有拷貝坛掠。
隱式捕獲:

可以用=和&表示lambda表達(dá)式是采用值捕獲還是引用捕獲

find_if(words.begin(), words.end(), [=](const string& a) { return a.size() > len; });

使用=號(hào)表示采用的是值捕獲(lambda表達(dá)式中所有的參數(shù)都是)。

find_if(words.begin(), words.end(), [&](const string& a) { return a.size() > len; });

使用&號(hào)表示采用的是引用捕獲(lambda表達(dá)式中所有的參數(shù)都是)治筒。

顯式和隱式捕獲混用:
for_each(words.begin(),  words.end(), [&, c] (const string &a) { os<< a << c; });

上面的lambda表達(dá)式中顯式聲明變量c采用值捕獲的方式屉栓,其余變量采用引用捕獲。

for_each(words.begin(),  words.end(), [=, &os] (const string &a) { os<< a << c; });

上面的lambda表達(dá)式中顯式聲明變量os采用引用捕獲的方式耸袜,其余變量采用值捕獲友多。

(5)指定lambda表達(dá)式的返回類(lèi)型

如前所述,如果要指定lambda表達(dá)式的返回值類(lèi)型堤框,必須使用尾置返回類(lèi)型域滥。

transform(v.begin(),  v.end(), v.begin(),  [](int i) { return i < 0 ? i : -i; });

上面的表達(dá)式是將數(shù)組v中的負(fù)數(shù)替換為絕對(duì)值,因?yàn)閘ambda表達(dá)式中只有一個(gè)return 語(yǔ)句蜈抓,因此可以不指定返回類(lèi)型启绰,編譯器會(huì)自動(dòng)推斷返回類(lèi)型為int。

但是若修改成:

transform(v.begin(), v.end(), v.begin(),  [](int i) { if(i < 0)  return -i; else return i;});

則會(huì)發(fā)生編譯報(bào)錯(cuò)沟使。需要采用尾置返回類(lèi)型修改委可。

transform(v.begin(), v.end(), v.begin(),  [] (int i)  -> int { if(i < 0)  return -i; else return i;});

這樣便指定了lambda表達(dá)式的返回類(lèi)型。

總結(jié):

(1)lambda表達(dá)式為匿名函數(shù)腊嗡,常用于在函數(shù)中傳遞謂詞着倾,如排序算法中傳遞是遞增排序還是遞減排序。
(2)lambda表達(dá)式采用引用捕獲參數(shù)的時(shí)候一定要保證在lambda表達(dá)式調(diào)用參數(shù)的時(shí)候變量一直存在叽唱。
(3)lambda表達(dá)式中如果只有一條return語(yǔ)句屈呕,返回類(lèi)型由編譯器自動(dòng)推斷;否則默認(rèn)返回void
(4)要指定lambda表達(dá)式的返回類(lèi)型要用尾置返回類(lèi)型棺亭。
(5)lambda表達(dá)式要盡量短;⒄!(類(lèi)似內(nèi)聯(lián)函數(shù))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嗽桩,更是在濱河造成了極大的恐慌岳守,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碌冶,死亡現(xiàn)場(chǎng)離奇詭異湿痢,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)扑庞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)譬重,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人罐氨,你說(shuō)我怎么就攤上這事臀规。” “怎么了栅隐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵塔嬉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我租悄,道長(zhǎng)谨究,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任泣棋,我火速辦了婚禮胶哲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘外傅。我一直安慰自己纪吮,他們只是感情好俩檬,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布萎胰。 她就那樣靜靜地躺著,像睡著了一般棚辽。 火紅的嫁衣襯著肌膚如雪技竟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天屈藐,我揣著相機(jī)與錄音榔组,去河邊找鬼。 笑死联逻,一個(gè)胖子當(dāng)著我的面吹牛搓扯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播包归,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锨推,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起换可,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤椎椰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后沾鳄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體慨飘,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年译荞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓤的。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吞歼,死狀恐怖堤瘤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浆熔,我是刑警寧澤本辐,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站医增,受9級(jí)特大地震影響慎皱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叶骨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一茫多、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忽刽,春花似錦天揖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至伞剑,卻和暖如春斑唬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黎泣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工恕刘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抒倚。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓褐着,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親托呕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子含蓉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容