1. lambda 函數概述
lambda 表達式是一種匿名函數,即沒有函數名的函數;該匿名函數是由數學中的λ演算而來的。通常情況下,lambda函數的語法定義為:
[capture] (parameters) mutable ->return-type {statement}
其中:
[capture] :捕捉列表。捕捉列表總是作為lambda的開始,即出現于lambda的開始處。它是lambda的引出符(即開始標志)。編譯器可以根據該“標志”來作出判斷出該函數是否為lambda函數。同時“捕捉列表”能夠捕捉上下文中的變量以作為lambda函數使用。
(parameters):參數列表。和C/C++中的普通函數參數意義一樣。該部分是可選的,意味著如果我們不需要進行參數傳遞時,可以連同括號“()”一起省略掉。
mutable:該關鍵字為一個修飾符。在默認的情況下,lambda函數總是返回一個const,而當我們在參數列表后面注明了“mutable”關鍵字之后,則可以取消其常量性質。若在lambda中使用了mutable修飾符,則“參數列表”是不可省略掉的(即使是參數為空)。
->return-type: 函數的返回值類型。和C/C++中的普通函數返回值類型的性質一樣。主要目的是用來追蹤lambda函數(有返回值情況下)的返回類型。若lambda函數不需要返回值,則可以直接將這部分省略掉。
{statement}:函數體。在該函數體中,除了可以使用參數列表中的變量外,還可以使用所有捕獲到的變量(即[capture] 中的變量)。
見下圖:

1.1. lambda 函數中“捕捉列表”詳解
C++11中的lambda函數,其中的“捕捉列表”是由0個或多個“捕捉項”組成,并以逗號“,”分隔。捕捉列表有如下幾種形式:
(1)[var] 表示值傳遞方式捕捉變量var。
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{int a = 1,b =2, c =3;auto retVal = [=,&a,&b](){printf("inner c[%d]n",c);a = 10;b = 20;return a+b;};printf("sum[%d]n",retVal());printf("a[%d] b[%d] c[%d]n",a,b,c);return 0;
}打印結果:
inner c[3]
sum[30]
a[10] b[20] c[3]
上面的代碼中,“捕捉列表”由3項組成。以引用傳遞的方式捕捉變量a、b,以值傳遞的方式捕捉變量c。因此在lambda表達式的函數體中修改了變量a和b之后,父作用域中的a、b值也改變。而即使是在lambda函數內部修改了變量c的值,父作用域中的c仍然不會受到影響,因為是值傳遞的方式。(需在參數列表后面加上 mutable 關鍵字(修飾符))。同時
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{int a = 1,b =2, c =3;auto retVal = [=,&a,&b]() mutable->int{printf("inner c[%d]n",c);a = 10;b = 20;c = 30;printf("inner c2[%d]n",c);return a+b;};printf("sum[%d]n",retVal());printf("a[%d] b[%d] c[%d]n",a,b,c);return 0;
}打印結果:
inner c[3]
inner c2[30]
sum[30]
a[10] b[20] c[3]
(2)[=] 表示值傳遞方式捕捉所有父作用域的變量(包括this)。
(3)[&var] 表示引用傳遞捕捉變量var。
(4)[&] 表示引用傳遞捕捉所有父作用域的比哪里(2020-02-18 09:36:12 修改) 的變量(包括this)。
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{int a = 1,b =2, c =3;auto retVal = [&]() mutable->int{printf("inner a[%d] b[%d] c[%d]n",a,b,c);a = 10;b = 20;c = 30;return a+b;};printf("sum[%d]n",retVal());printf("a[%d] b[%d] c[%d]n",a,b,c);return 0;
}打印結果:
inner a[1] b[2] c[3]
sum[30]
a[10] b[20] c[30]
(5)[this] 表示值傳遞方式捕捉當前的this指針。
同理(2),(3),(5)可以參考上面的兩個例子。
2. lambda 函數特點
(1)在C++11中,lambda函數是inline(內聯函數)。
3. lambda 函數使用
代碼一
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{int a = 6;int b = 8;auto sum = [](int a,int b) ->int{return a + b;};printf("sum[%d]n",sum(a,b));return 0;
}//打印結果:sum[14]
在代碼一中,定義了一個簡單的lambda函數,該函數的函數列表能夠接收兩個int類型的數據,而且返回值為int類型。
注意:lambda函數中,參數列表和返回類型都是可選的部分,而且捕捉列表和函數也可以為空。因此,在某種情況下,C++11中的簡略版本的lambda函數可以是這樣的:
// 完整語法
[ capture-list ] ( params ) mutable(optional) constexpr(optional)(c++17) exception attribute -> ret { body } // 可選的簡化語法
[ capture-list ] ( params ) -> ret { body }
[ capture-list ] ( params ) { body }
最為簡潔的版本如下, 多謝讀者「-兮」 的指正。已將[]()
修改為了[]{}
[ capture-list ] { body }
代碼二
在C++開發中,
4. lambda 函數與 STL
更多技術干貨見個人微信公眾號: 雅俗不共賞 掃碼關注不迷路~
http://weixin.qq.com/r/NhIjOz-EnWLirXtY90ck (二維碼自動識別)