C++ lambda表達式入門
- 1. 定義
- 2. lambda表達式的使用
-
- 2.1 最簡單的 lambda表達式
- 2.2 加上參數清單
- 2.3 再加點列印的東西
- 2.4 傳回值
- 2.5 捕捉變量
- 2.6 STL應用
Reference:
- C++ lambda表達式入門
1. 定義
lambda 表達式 就是一個(匿名)函數,也就是一個沒有函數名的函數。為什麼不需要函數名呢,因為我們一次性的用它,嵌入式用的它,不需要在其他地方調用它。
lambda 表達式也叫閉包,閉就是封閉(其他地方都不調用)的意思,包就是函數。
lambda 表達式其實就是一個函數對象,他内部建立了一個重載()操作符的類。
lambda 表達式的簡單文法如下:[capture] (parameters) -> return value { body },隻有 [capture] 捕獲清單和 { body } 函數體是必選的,其他可選。
建立 lambda函數的一個原因是有些人希望建立一個能接受(lambda函數)參數的函數。
lambda 的引入給我們帶來了一種全新的程式設計體驗,它可以讓我們把 function 當做是 data 一樣傳遞,并且使我們從繁瑣的文法中解放出來,更加關注于“算法”本身。
新的
std::function
是傳遞 lambda函數的最好方式,不管是傳遞參數還是傳回值。
2. lambda表達式的使用
2.1 最簡單的 lambda表達式
int main()
{
[] {}();//三部分,[] : 代表lambda表達式的開始;{} : 代表函數體,函數體裡面什麼都沒有;() : 代表函數調用.
}
等價于:
void f()
{
}
int main()
{
f();
}
2.2 加上參數清單
像其他函數一樣,我們需要一個參數清單
()
,這樣
[] {}()
也可以寫為:
[](){}();
加了一個
()
代表函數參數,如果什麼參數都沒有,可以忽略
()
。
2.3 再加點列印的東西
int main()
{
[] { cout << "Hello, World!"<<endl; }();
}
也可以這樣:
int main()
{
auto lam = [] { cout << "Hello, World!"<<endl; };
lam();
}
2.4 傳回值
-> 代表此匿名函數傳回 int。大多數情況下 lambda表達式 的傳回值可由編譯器猜測得出,是以不需要特别指定傳回值類型。
int main()
{
auto lam =[]() -> int { cout << "Hello, World!"; return 88; };
//auto lam =[]() { cout << "Hello, World!"; return 88; };//自動推導傳回值
auto ret = lam();
cout<<ret<<endl;//輸出88
auto lam2 =[]() -> string { cout << "Hello, World!"; return "test"; };
auto ret1 = lam2();
cout<<ret1<<endl;//輸出test
}
2.5 捕捉變量
變量捕捉才是成就 lambda表達式 卓越的秘方。
-
: 不捕獲任何變量,這種情況下 lambda表達式 内部不能通路外部的變量;[]
-
:以引用方式捕獲所有變量;[&]
-
:用值的方式捕獲所有變量 (可能被編譯器優化為 const &);[=]
-
:以引用方式捕獲變量[=, &foo]
,但其餘變量都靠值捕獲;foo
-
:以值方式捕獲[&,foo]
,但其餘變量都靠引用捕獲;foo
-
:以值方式捕獲[bar]
,不捕獲其他變量;bar
-
:捕獲所在類的[this]
指針 (Qt 中使用很多,如此 lambda 可以通過 this 通路界面控件的資料)this
int a=1,b=2,c=3;
auto lam2 = [&,a](){//b,c以引用捕獲,a以值捕獲。
b=5;c=6;//a =1; a不能指派
cout << a<<b<<c<<endl;//輸出 1 5 6
};
lam2();
2.6 STL應用
毋庸置疑,lambda 最大的一個優勢是在使用 STL 算法庫時:
vector<string> address{"111","222",",333",".org","wwwtest.org"};
for_each(address.begin(),address.end(),[](const string& str){cout<<str<<endl;});
// for_each為STL [](const string& str){cout<<str<<endl;}為lambda表達式
如此一行代碼就可以循環列印容器的資料。
再看一個例子,以前數組排序代碼是這樣的:
int arr[] = {6,4,3,2,1,5};
bool compare(int& a,int& b)//謂詞函數
{
return a>b;
}
std::sort(arr, arr+6, compare);
用 lambda 表示:
std::sort(arr, arr+6, [](const int& a,const int& b){return a>b;});//降序排序
//std::sort(arr, arr+6, [](const auto& a,const auto& b){return a>b;}); //C++14支援基于類型推斷的泛型lambda表達式。
std::for_each(begin(arr),end(arr),[](const int& e){cout<<"After:"<<e<<endl;});//6,5,4,3,2,1
lambda表達式取代了謂詞函數,一行代碼搞定排序,再一行代碼搞定列印數組所有資料。