C++11 Lambda表達(dá)式

本文根據(jù)眾多互聯(lián)網(wǎng)博客內(nèi)容整理后形成,引用內(nèi)容的版權(quán)歸原始作者所有,僅限于學(xué)習(xí)研究使用,不得用于任何商業(yè)用途。

C++11引入了lambda表達(dá)式,使得程序員可以定義匿名函數(shù),該函數(shù)是一次性執(zhí)行的,既方便了編程饲做,又能防止別人的訪問塞弊。
Lambda表達(dá)式的語法通過下圖來介紹:



這里假設(shè)我們定義了一個如上圖的lambda表達(dá)式。現(xiàn)在來介紹途中標(biāo)有編號的各個部分是什么意思。

  • Lambda表達(dá)式的引入標(biāo)志游沿,在‘[]’里面可以填入‘=’或‘&’表示該lambda表達(dá)式“捕獲”(lambda表達(dá)式在一定的scope可以訪問的數(shù)據(jù))的數(shù)據(jù)時以什么方式捕獲的饰抒,‘&’表示以引用的方式;‘=’表明以值傳遞的方式捕獲诀黍,除非專門指出袋坑。
  • Lambda表達(dá)式的參數(shù)列表
  • Mutable 標(biāo)識
  • 異常標(biāo)識
  • 返回值
  • “函數(shù)”體,也就是lambda表達(dá)式需要進(jìn)行的實際操作

Lambda表達(dá)式是一種描述函數(shù)對象的機(jī)制眯勾,它的主要應(yīng)用是描述某些具有簡單行為的函數(shù)(譯注:Lambda表達(dá)式也可以稱為匿名函數(shù)咒彤,具有復(fù)雜行為的函數(shù)可以采用命名函數(shù)對象,當(dāng)然,何謂復(fù)雜咒精,何謂簡單镶柱,這取決于編程人員的個人選擇)。例如:

vector<int> v = {50, -10, 20, -30};
std::sort(v.begin(), v.end()); // 排序時按照默認(rèn)規(guī)則
// 此時v中的數(shù)據(jù)應(yīng)該是 { -30, -10, 20, 50 }

// 利用Lambda表達(dá)式模叙,按照絕對值排序
std::sort(v.begin(), v.end(), [](int a, int b){ return abs(a)<abs(b); });
// 此時v應(yīng)該是 { -10, 20, -30, 50 }

函數(shù) [](int a, int b) { return abs(a) < abs(b); }
是一個具有如下行為的"lambda":接受兩個整數(shù)a和b歇拆,然后返回對它們的絕對值進(jìn)行"<"比較的結(jié)果。
Lambda表達(dá)式可以訪問在它被調(diào)用的作用域內(nèi)的局部變量范咨。例如:

void f(vector<Record>& v)
{ 
  vector<int> indices(v.size()); 
  int count = 0;
  generate(indices.begin(),indices.end(),[&count]()
  { return count++; }); 
  
  // 對indices按照記錄的名字域順序進(jìn)行排序  
  std::sort(indices.begin(), indices.end(), [&](int a, int b) 
  { return  v[a].name<v[b].name; }); 
  // ...
}

有人認(rèn)為這“相當(dāng)簡潔”故觅,也有人認(rèn)為這是一種可能產(chǎn)生危險且晦澀的代碼的方式。我的看法是渠啊,兩者都正確输吏。

  • [&] 是一個“捕捉列表(capture list)”,用于描述將要被lambda函數(shù)以引用傳參方式使用的局部變量替蛉。
  • 如果我們僅想“捕捉”參數(shù)v贯溅,則可以寫為: [&v]。
  • 而如果我們想以傳值方式使用參數(shù)v躲查,則可以寫為:[=v]它浅。
  • 如果什么都不捕捉,則為:[]镣煮。
  • 將所有的變量以引用傳遞方式使用時采用[&], 而相對地姐霍,使用[=] 則相應(yīng)地表示以傳值方式使用所有變量。
    (譯注:“所有變量”即指lambda表達(dá)式在被調(diào)用處典唇,所能見到的所有局部變量)

如果某一函數(shù)的行為既不通用也不簡單镊折,那么我建議采用命名函數(shù)對象或者函數(shù)。例如介衔,如上示例可重寫為:

void f( vector<Record>& v)
{
  vector<int> indices(v.size() ); 
  int count = 0; 
  fill(indices.begin(), indices.end(), [&]() 
  { return ++count; }; 

  struct Cmp_names {
    const vector& vr; 
    Cmp_names(const vector<Record>& r) : vr(r) {} 
    bool operator() (Record& a, Record& b) const { return vr[a] < vr[b]; } 
  }; 

  //對indices按照記錄的名字域順序進(jìn)行排序 
  std::sort(indices.begin(), indices.end(), Cmp_names(v) ); 
}

(譯注:此處采用了函數(shù)對象Cmp_names(v)來代替lambda表達(dá)式恨胚,由于Cmp_names具有以引用傳參方式的構(gòu)造函數(shù),因此Cmp_names(v)相當(dāng)于使用了”[&v]”的lambda表達(dá)式)

對于簡單的函數(shù)功能夜牡,比如記錄名稱域的比較与纽,采用函數(shù)對象就略顯冗長,盡管它與lambda表達(dá)式生成的代碼是一致的塘装。在C++98中急迂,這樣的函數(shù)對象在被用作模板參數(shù)時必須是“非本地”的(譯注:即你不能在函數(shù)對象中像此處的lambda表達(dá)式那樣使用被調(diào)用處的局部變量),然而在C++中(譯注:意指C++0x)蹦肴,這不再是必須的僚碎。

為了描述一個lambda,你必須提供:

  • 它的捕捉列表:即(除了形參之外)它可以使用的變量列表(”[&]” 在上面的記錄比較例子中意味著“所有的局部變量都將按照引用的方式進(jìn)行傳遞”)阴幌。如果不需要捕捉任何變量勺阐,則使用 []。
  • (可選的)它的所有參數(shù)及其類型(例如: (int a, int b))矛双。
  • 組織成一個塊的函數(shù)行為(例如:{ return v[a].name < v[b].name; })渊抽。
  • (可選的)使用”返回值類型后置語法“來指明返回類型。但典型情況下议忽,我們僅從return語句中去推斷返回類型懒闷,如果沒有返回任何值,則推斷為void栈幸。

int n = [] (int x, int y) { return x + y; }(5, 4);
cout << n << endl;

參考資料
Lambda表達(dá)式 | cpp11新特性詳解與應(yīng)用
Lambda表達(dá)式 | C++11 FAQ 中文版
C++11 lambda表達(dá)式 - KingsLanding
用作模板參數(shù)的局部類型 | C++11 FAQ 中文版

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愤估,一起剝皮案震驚了整個濱河市固歪,隨后出現(xiàn)的幾起案子仇轻,更是在濱河造成了極大的恐慌,老刑警劉巖募疮,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芍锚,死亡現(xiàn)場離奇詭異昔园,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)并炮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蒿赢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渣触,你說我怎么就攤上這事羡棵。” “怎么了嗅钻?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵皂冰,是天一觀的道長。 經(jīng)常有香客問我养篓,道長秃流,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任柳弄,我火速辦了婚禮舶胀,結(jié)果婚禮上概说,老公的妹妹穿的比我還像新娘。我一直安慰自己嚣伐,他們只是感情好糖赔,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轩端,像睡著了一般放典。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上基茵,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天奋构,我揣著相機(jī)與錄音,去河邊找鬼拱层。 笑死弥臼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的根灯。 我是一名探鬼主播醋火,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼箱吕!你這毒婦竟也來了芥驳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茬高,失蹤者是張志新(化名)和其女友劉穎兆旬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怎栽,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡丽猬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了熏瞄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脚祟。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖强饮,靈堂內(nèi)的尸體忽然破棺而出由桌,到底是詐尸還是另有隱情,我是刑警寧澤邮丰,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布行您,位于F島的核電站,受9級特大地震影響剪廉,放射性物質(zhì)發(fā)生泄漏娃循。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一斗蒋、第九天 我趴在偏房一處隱蔽的房頂上張望捌斧。 院中可真熱鬧笛质,春花似錦、人聲如沸捞蚂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洞难。三九已至舆吮,卻和暖如春揭朝,著一層夾襖步出監(jiān)牢的瞬間队贱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工潭袱, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留柱嫌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓屯换,卻偏偏與公主長得像编丘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子彤悔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

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

  • 簡介 概念 Lambda 表達(dá)式可以理解為簡潔地表示可傳遞的匿名函數(shù)的一種方式:它沒有名稱嘉抓,但它有參數(shù)列表、函數(shù)主...
    劉滌生閱讀 3,204評論 5 18
  • 聲明:本文翻譯自The Java? Tutorials(官方文檔) 簡述 匿名類有一個問題晕窑,如果匿名類的實現(xiàn)非常簡...
    猴子小皮球閱讀 4,663評論 0 9
  • C++ lambda表達(dá)式與函數(shù)對象 lambda表達(dá)式是C++11中引入的一項新技術(shù)抑片,利用lambda表達(dá)式可以...
    小白將閱讀 85,252評論 15 118
  • 我望著前面蠕動的人群,身邊的孩子來去匆匆杨赤,北京的交通太冷敞斋,人們都排著隊等著取暖。抬著頭看著這被霧霾愛著的天空疾牲,灰姑...
    西樓魚閱讀 185評論 0 0
  • 2013年10月22日植捎。遙遠(yuǎn)的夢想,在深秋的路燈下再也耀不出光芒阳柔。因為迷失了方向焰枢,在那一瞬間天...
    會旅行的小漢子閱讀 387評論 0 0