c++11中的lambda

//zz https://www.cnblogs.com/DswCnblog/p/5629165.html

c++11編譯開關(guān):???g++ -std=c++11

C++11的一大亮點就是引入了Lambda表達(dá)式。利用Lambda表達(dá)式,可以方便的定義和創(chuàng)建匿名函數(shù)渔扎。對于C++這門語言來說來說,“Lambda表達(dá)式”或“匿名函數(shù)”這些概念聽起來好像很深奧,但很多高級語言在很早以前就已經(jīng)提供了Lambda表達(dá)式的功能鞋囊,如C#甸陌,Python等。今天近哟,我們就來簡單介紹一下C++中Lambda表達(dá)式的簡單使用驮审。

聲明Lambda表達(dá)式

Lambda表達(dá)式完整的聲明格式如下:

[capture list] (paramslist) mutable exception->returntype { function body }

各項具體含義如下

capture list:捕獲外部變量列表

params list:形參列表

mutable指示符:用來說用是否可以修改捕獲的變量

exception:異常設(shè)定

return type:返回類型

function body:函數(shù)體

此外,我們還可以省略其中的某些成分來聲明“不完整”的Lambda表達(dá)式吉执,常見的有以下幾種:

序號格式

1[capture list] (params list) -> return type {function body}

2[capture list] (params list) {function body}

3[capture list] {function body}

其中:

格式1聲明了const類型的表達(dá)式疯淫,這種類型的表達(dá)式不能修改捕獲列表中的值。

格式2省略了返回值類型戳玫,但編譯器可以根據(jù)以下規(guī)則推斷出Lambda表達(dá)式的返回類型: (1):如果function

body中存在return語句熙掺,則該Lambda表達(dá)式的返回類型由return語句的返回類型確定; (2):如果function

body中沒有return語句咕宿,則返回值為void類型币绩。

格式3中省略了參數(shù)列表,類似普通函數(shù)中的無參函數(shù)府阀。

講了這么多缆镣,我們還沒有看到Lambda表達(dá)式的廬山真面目,下面我們就舉一個實例试浙。

#include #include #include usingnamespace std;boolcmp(inta,int b)

{

? ? returna < b;

}int main()

{

? ? vector myvec{3,2,5,7,3,2 };

? ? vector lbvec(myvec);

? ? sort(myvec.begin(), myvec.end(), cmp); // 舊式做法cout <<"predicate function:"<< endl;

? ? for(int it : myvec)

? ? ? ? cout << it <<'';

? ? cout << endl;

? ? sort(lbvec.begin(), lbvec.end(), [](inta,intb) ->bool{returna < b; });// Lambda表達(dá)式cout <<"lambda expression:"<< endl;

? ? for(int it : lbvec)

? ? ? ? cout << it <<'';

}

在C++11之前董瞻,我們使用STL的sort函數(shù),需要提供一個謂詞函數(shù)田巴。如果使用C++11的Lambda表達(dá)式钠糊,我們只需要傳入一個匿名函數(shù)即可挟秤,方便簡潔,而且代碼的可讀性也比舊式的做法好多了抄伍。

下面艘刚,我們就重點介紹一下Lambda表達(dá)式各項的具體用法。

捕獲外部變量

Lambda表達(dá)式可以使用其可見范圍內(nèi)的外部變量截珍,但必須明確聲明(明確聲明哪些外部變量可以被該Lambda表達(dá)式使用)昔脯。那么,在哪里指定這些外部變量呢笛臣?Lambda表達(dá)式通過在最前面的方括號[]來明確指明其內(nèi)部可以訪問的外部變量云稚,這一過程也稱過Lambda表達(dá)式“捕獲”了外部變量。

我們通過一個例子來直觀地說明一下:

#include usingnamespace std;int main()

{

? ? inta =123;

? ? auto f = [a] { cout << a << endl; };

? ? f(); // 輸出:123

? ? //或通過“函數(shù)體”后面的‘()’傳入?yún)?shù)auto x = [](inta){cout << a << endl;}(123);

}

上面這個例子先聲明了一個整型變量a沈堡,然后再創(chuàng)建Lambda表達(dá)式静陈,該表達(dá)式“捕獲”了a變量,這樣在Lambda表達(dá)式函數(shù)體中就可以獲得該變量的值诞丽。

類似參數(shù)傳遞方式(值傳遞鲸拥、引入傳遞、指針傳遞)僧免,在Lambda表達(dá)式中刑赶,外部變量的捕獲方式也有值捕獲、引用捕獲懂衩、隱式捕獲撞叨。

1、值捕獲

值捕獲和參數(shù)傳遞中的值傳遞類似浊洞,被捕獲的變量的值在Lambda表達(dá)式創(chuàng)建時通過值拷貝的方式傳入牵敷,因此隨后對該變量的修改不會影響影響Lambda表達(dá)式中的值。

示例如下:

int main()

{

? ? inta =123;

? ? auto f = [a] { cout << a << endl; };

? ? a =321;

? ? f(); // 輸出:123}

這里需要注意的是法希,如果以傳值方式捕獲外部變量枷餐,則在Lambda表達(dá)式函數(shù)體中不能修改該外部變量的值。

2苫亦、引用捕獲

使用引用捕獲一個外部變量毛肋,只需要在捕獲列表變量前面加上一個引用說明符&。如下:

int main()

{

? ? inta =123;

? ? auto f = [&a] { cout << a << endl; };

? ? a =321;

? ? f(); // 輸出:321}

從示例中可以看出屋剑,引用捕獲的變量使用的實際上就是該引用所綁定的對象润匙。

3、隱式捕獲

上面的值捕獲和引用捕獲都需要我們在捕獲列表中顯示列出Lambda表達(dá)式中使用的外部變量饼丘。除此之外趁桃,我們還可以讓編譯器根據(jù)函數(shù)體中的代碼來推斷需要捕獲哪些變量辽话,這種方式稱之為隱式捕獲肄鸽。隱式捕獲有兩種方式卫病,分別是[=]和[&]。[=]表示以值捕獲的方式捕獲外部變量典徘,[&]表示以引用捕獲的方式捕獲外部變量蟀苛。

隱式值捕獲示例:

int main()

{

? ? inta =123;

? ? auto f = [=] { cout << a << endl; };// 值捕獲f();// 輸出:123}

隱式引用捕獲示例:

int main()

{

? ? inta =123;

? ? auto f = [&] { cout << a << endl; };// 引用捕獲a =321;

? ? f(); // 輸出:321}

4、混合方式

上面的例子逮诲,要么是值捕獲帜平,要么是引用捕獲,Lambda表達(dá)式還支持混合的方式捕獲外部變量梅鹦,這種方式主要是以上幾種捕獲方式的組合使用裆甩。

到這里,我們來總結(jié)一下:C++11中的Lambda表達(dá)式捕獲外部變量主要有以下形式:

捕獲形式說明

[]不捕獲任何外部變量

[變量名, …]默認(rèn)以值得形式捕獲指定的多個外部變量(用逗號分隔)齐唆,如果引用捕獲嗤栓,需要顯示聲明(使用&說明符)

[this]以值的形式捕獲this指針

[=]以值的形式捕獲所有外部變量

[&]以引用形式捕獲所有外部變量

[=, &x]變量x以引用形式捕獲,其余變量以傳值形式捕獲

[&, x]變量x以值的形式捕獲箍邮,其余變量以引用形式捕獲

修改捕獲變量

前面我們提到過茉帅,在Lambda表達(dá)式中,如果以傳值方式捕獲外部變量锭弊,則函數(shù)體中不能修改該外部變量堪澎,否則會引發(fā)編譯錯誤。那么有沒有辦法可以修改值捕獲的外部變量呢味滞?這是就需要使用mutable關(guān)鍵字樱蛤,該關(guān)鍵字用以說明表達(dá)式體內(nèi)的代碼可以修改值捕獲的變量,示例:

int main()

{

? ? inta =123;

? ? auto f = [a]()mutable { cout << ++a; };// 不會報錯cout << a << endl;// 輸出:123f();// 輸出:124}

Lambda表達(dá)式的參數(shù)

Lambda表達(dá)式的參數(shù)和普通函數(shù)的參數(shù)類似剑鞍,那么這里為什么還要拿出來說一下呢刹悴?原因是在Lambda表達(dá)式中傳遞參數(shù)還有一些限制,主要有以下幾點:

參數(shù)列表中不能有默認(rèn)參數(shù)

不支持可變參數(shù)

所有參數(shù)必須有參數(shù)名

常用舉例:

{

intm = [](intx) {return[](inty) {returny *2; }(x)+6; }(5);

? ? ? ? std::cout <<"m:"<< m << std::endl;//輸出m:16? ? ? ? std::cout <<"n:"<< [](intx,inty) {returnx + y; }(5,4) << std::endl;//輸出n:9? ? ? ?

? ? ? ? auto gFunc = [](intx) -> function {return[=](inty) {returnx + y; }; };

? ? ? ? auto lFunc = gFunc(4);

? ? ? ? std::cout << lFunc(5) << std::endl;

? ? ? ? auto hFunc = [](constfunction& f,intz) {returnf(z) +1; };

? ? ? ? auto a = hFunc(gFunc(7),8);

? ? ? ? inta =111, b =222;

? ? ? ? auto func = [=, &b]()mutable { a =22; b =333; std::cout <<"a:"<< a <<" b:"<< b << std::endl; };

? ? ? ? func();

? ? ? ? std::cout <<"a:"<< a <<" b:"<< b << std::endl;

? ? ? ? a =333;

? ? ? ? auto func2 = [=, &a] { a =444; std::cout <<"a:"<< a <<" b:"<< b << std::endl; };

? ? ? ? func2();

? ? ? ? auto func3 = [](intx) ->function {return[=](inty) {returnx + y; }; };

     std::function?f_display_42?=?[](int?x)?{?print_num(x);?};

f_display_42(44);

  }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攒暇,一起剝皮案震驚了整個濱河市土匀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌形用,老刑警劉巖就轧,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異田度,居然都是意外死亡妒御,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門镇饺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乎莉,“玉大人,你說我怎么就攤上這事⊥锟校” “怎么了哼鬓?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長边灭。 經(jīng)常有香客問我异希,道長,這世上最難降的妖魔是什么绒瘦? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任称簿,我火速辦了婚禮,結(jié)果婚禮上惰帽,老公的妹妹穿的比我還像新娘憨降。我一直安慰自己,他們只是感情好该酗,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布券册。 她就那樣靜靜地躺著,像睡著了一般垂涯。 火紅的嫁衣襯著肌膚如雪烁焙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天耕赘,我揣著相機(jī)與錄音骄蝇,去河邊找鬼。 笑死操骡,一個胖子當(dāng)著我的面吹牛九火,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播册招,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼岔激,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了是掰?” 一聲冷哼從身側(cè)響起虑鼎,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎键痛,沒想到半個月后炫彩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡絮短,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年江兢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丁频。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡杉允,死狀恐怖邑贴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叔磷,我是刑警寧澤拢驾,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站世澜,受9級特大地震影響独旷,放射性物質(zhì)發(fā)生泄漏署穗。R本人自食惡果不足惜寥裂,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一塞琼、第九天 我趴在偏房一處隱蔽的房頂上張望坯墨。 院中可真熱鬧,春花似錦越庇、人聲如沸褐啡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽备畦。三九已至低飒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間懂盐,已是汗流浹背褥赊。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留莉恼,地道東北人拌喉。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像俐银,于是被迫代替她去往敵國和親尿背。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

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

  • 接著上節(jié) condition_varible 捶惜,本節(jié)主要介紹future的內(nèi)容田藐,練習(xí)代碼地址。本文參考http:/...
    jorion閱讀 14,776評論 1 5
  • 空指針 nullptr 空指針的字面值常量吱七,它的類型是std::nullptr_t(定義位于cstddef) 自動...
    龍遁流閱讀 480評論 1 2
  • lambda表達(dá)式是C++11引入的新特性坞淮,用于聲明一個函數(shù),因為不需要對這個函數(shù)指定函數(shù)名陪捷,故lambda表達(dá)式...
    銘小汁兒閱讀 493評論 0 2
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,511評論 1 51
  • 繁花盛開 我在你的手機(jī)屏幕的跟前 你我各自 妙筆生花 繁花凋零 卻不改你我的熱情 碼字是一種幸福 碼了便足矣
    Ling_00閱讀 115評論 0 6