C++霧中風(fēng)景8:Lambda表達(dá)式

上一篇C++的博客是Long Long ago了,前文講到在看Lambda表達(dá)式的內(nèi)容。筆者首次接觸Lambda表達(dá)式應(yīng)該是學(xué)習(xí)Python語(yǔ)言的時(shí)候陈肛,當(dāng)時(shí)也不太明白這種表達(dá)方式的精髓逗柴,后續(xù)接觸了Scala與Java8的鏈?zhǔn)秸{(diào)用與Lambda結(jié)合的方式,深陷無(wú)法自拔矢渊。所以借上一篇閉包的內(nèi)容。我們來(lái)完整的梳理一下C++之中的Lambda表達(dá)式。

1.什么是Lambda表達(dá)式狸相?

Lambda表達(dá)式是函數(shù)式編程的重要的語(yǔ)法結(jié)構(gòu)。
Lambda 表達(dá)式(lambda expression)說(shuō)起來(lái)很簡(jiǎn)單捐川,就是一個(gè)匿名函數(shù)脓鹃,即沒(méi)有函數(shù)名的函數(shù)。Lambda表達(dá)式可以表示閉包古沥。(注意和數(shù)學(xué)傳統(tǒng)意義上的不同)瘸右。(本質(zhì)上Lambda表達(dá)式就是將函數(shù)作為是一個(gè)匿名對(duì)象進(jìn)行操作

其實(shí)缺少Lambda表達(dá)式的編程語(yǔ)言并不會(huì)影響編程語(yǔ)言的邏輯表達(dá),Lambda表達(dá)式核心就是提供一個(gè)好用的語(yǔ)法糖:可以直接定義一個(gè)函數(shù)岩齿,而不需要將定義函數(shù)和語(yǔ)法內(nèi)容分開太颤,這樣有助于將邏輯用更緊湊的方式表達(dá)出來(lái)。假如需要定義一個(gè)函數(shù)盹沈,恰巧這個(gè)函數(shù)僅僅使用一次龄章,然后又需要給它定義一個(gè)名字,作為懶惰的程序員就需要搬出Lambda表達(dá)式了乞封。咱們看一段Python代碼做裙,過(guò)濾一個(gè)list之中的偶數(shù),這是一個(gè)很簡(jiǎn)單的需求肃晚,我們先看看不使用Lambda表達(dá)式的方式:

def isOdd(n):
    return n & 1;

nums = [1,2,3,4,5,6]
nums = filter(isOdd,nums)

顯然這里需要額外定義一個(gè)代碼邏輯十分麻煩:首先需要跳脫出運(yùn)行代碼而去查看定義的isOdd函數(shù)的代碼锚贱,其次,這里需要實(shí)現(xiàn)的過(guò)濾邏輯很簡(jiǎn)單关串。這種場(chǎng)合是最適合使用Lambda表達(dá)式的場(chǎng)景惋鸥,我們來(lái)看看Lambda表達(dá)式是怎么優(yōu)化上述代碼的:

nums = [1,2,3,4,5,6]
nums = filter(lambda x:x & 1,nums)

好吧,很優(yōu)雅的用Lambda表達(dá)式解決了同樣的需求悍缠,表述也十分清晰:
下面的幾個(gè)使用場(chǎng)景是適用于Lambda表達(dá)式的:

  • (1)代碼定義的邏輯與執(zhí)行邏輯對(duì)接的更加緊湊卦绣。
  • (2)代碼更加簡(jiǎn)潔。
  • (3)能夠支持閉包飞蚓。

2.C++之中的Lambda表達(dá)式

C++在C++11之中添加了Lambda表達(dá)式的語(yǔ)法結(jié)構(gòu)滤港,Lambda語(yǔ)法結(jié)構(gòu)如下所示:

[capture](parameters)->return-type {body}

接下來(lái),我們來(lái)一一分析各個(gè)部分所代表的含義,以及具體的使用方式:

  • [capture]
    capture代表捕獲外部的變量溅漾,這個(gè)使用的方式筆者在上一篇有關(guān)閉包的內(nèi)容之中就有過(guò)示例山叮,變量捕獲是Lambda表達(dá)式之中,最為復(fù)雜的一環(huán)添履,我們來(lái)看一看其中各種表示方式的含義:
    • [] 不捕獲任何變量(但是必須得寫屁倔,編譯器通過(guò)捕獲結(jié)構(gòu)識(shí)別Lambda表達(dá)式
    • [&} 通過(guò)引用的方式捕獲外部作用域中所有變量
    • [=] 通過(guò)拷貝的方式捕獲外部作用域中所有變量
      上述兩種方式都過(guò)于粗暴了,實(shí)際的話暮胧,盡量采用下面的模式來(lái)限定所引用的變量锐借,不要隨意引用
    • [x, &y] x按值傳遞,y按引用傳遞
    • [this] 截取當(dāng)前類中的this指針往衷。如果已經(jīng)使用了&或者=就默認(rèn)添加此選項(xiàng)钞翔。

可以看到,[capture]的語(yǔ)法結(jié)構(gòu)捕獲了外部變量席舍,通過(guò)這樣的方式實(shí)現(xiàn)了閉包布轿。

  • (parameters)
    這個(gè)部分很簡(jiǎn)單,類似于通常函數(shù)使用的參數(shù)列表来颤,使用方式也沒(méi)有區(qū)別汰扭。

  • ->return-type
    顯式指明由Lambda表達(dá)式所返回的返回值類型。這里通常建議不寫福铅,因?yàn)镃++編譯器會(huì)通過(guò)類型推斷的方式來(lái)推斷出函數(shù)的返回值類型东且,而且前面的->也可以省略。

  • {body}
    花括號(hào)括起來(lái)的函數(shù)體本讥,則沒(méi)什么好說(shuō)的了,就是實(shí)現(xiàn)函數(shù)邏輯的部分了鲁冯。

同樣的拷沸,我們來(lái)看看上文用python實(shí)現(xiàn)的過(guò)濾偶數(shù)的代碼在C++之中是如何實(shí)現(xiàn)的:

    vector<int> nums = {1,2,3,4,5,6,7};
    vector<int> newNums(nums.size());
    
    auto last = copy_if(nums.cbegin(), nums.cend(),newNums.begin(),[](int x){return !(x & 1);});
    for_each(newNums.begin(), last, [](int x) {
        cout << x << endl;
    });

和python的實(shí)現(xiàn)相比,由于缺少了鏈?zhǔn)秸{(diào)用的方式薯演,所以看起來(lái)C++實(shí)現(xiàn)的版本并沒(méi)有簡(jiǎn)化多少應(yīng)用邏輯撞芍,反而看起來(lái)略顯雜亂。但是這并不妨礙我們?cè)谶m當(dāng)?shù)牡胤竭\(yùn)用Lambda表達(dá)式跨扮,來(lái)優(yōu)化我們的代碼結(jié)構(gòu)序无。

3.其他語(yǔ)言與Lambda表達(dá)式

  • Java
    Java在Java 8的版本終于千呼萬(wàn)喚始出來(lái)的Lambda表達(dá)式確實(shí)是讓個(gè)人很喜歡,個(gè)人也覺(jué)得Java 8對(duì)于Java這門語(yǔ)言有極其深遠(yuǎn)的影響衡创。我們來(lái)看看Java之中是如何實(shí)現(xiàn)上文的邏輯的:
public static void main(String[] args) {
        int[] nums = {1,2,3,4,5,6,7};
        IntStream.of(nums).filter((x)->{return (x & 1) == 1;}).forEach(System.out::println);
    }

相比C++而言優(yōu)雅了很多帝嗡,而且參數(shù)類型也能做到類型推斷,對(duì)程序員來(lái)說(shuō)確實(shí)更加友好了璃氢。

坦白說(shuō):Java是一門很幸運(yùn)的語(yǔ)言哟玷,更上了移動(dòng)開發(fā),大數(shù)據(jù)的浪潮一也。不過(guò)隨著Google與Oracle的官司巢寡,不知道Java未來(lái)是否還能繼續(xù)現(xiàn)在的強(qiáng)勢(shì)地位喉脖。

  • Golang
    沒(méi)有Lambda表達(dá)式,咱們要的是簡(jiǎn)潔明晰抑月,不要學(xué)Geek那一套玩意树叽。

4.小結(jié)

感覺(jué)本文干貨有點(diǎn)略少,吐槽略多谦絮,見(jiàn)諒哈~~~题诵。關(guān)于C++之中的Lambda表達(dá)式就和大家聊到這里,希望大家在實(shí)際Coding之中可以用好它挨稿,來(lái)盡量簡(jiǎn)潔化自己的代碼結(jié)構(gòu)仇轻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奶甘,隨后出現(xiàn)的幾起案子篷店,更是在濱河造成了極大的恐慌,老刑警劉巖臭家,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疲陕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡钉赁,警方通過(guò)查閱死者的電腦和手機(jī)蹄殃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)你踩,“玉大人诅岩,你說(shuō)我怎么就攤上這事〈ぃ” “怎么了吩谦?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)膝藕。 經(jīng)常有香客問(wèn)我式廷,道長(zhǎng),這世上最難降的妖魔是什么芭挽? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任滑废,我火速辦了婚禮,結(jié)果婚禮上袜爪,老公的妹妹穿的比我還像新娘蠕趁。我一直安慰自己,他們只是感情好辛馆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布妻导。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪倔韭。 梳的紋絲不亂的頭發(fā)上术浪,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音寿酌,去河邊找鬼胰苏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醇疼,可吹牛的內(nèi)容都是我干的硕并。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼秧荆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼倔毙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起乙濒,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤陕赃,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后颁股,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體么库,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年甘有,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诉儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亏掀,死狀恐怖忱反,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滤愕,我是刑警寧澤温算,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站该互,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏韭畸。R本人自食惡果不足惜宇智,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胰丁。 院中可真熱鬧随橘,春花似錦、人聲如沸锦庸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至萝嘁,卻和暖如春梆掸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牙言。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工酸钦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咱枉。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓卑硫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蚕断。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欢伏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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