lambda表達式是C++11最重要也是最常用的一個特性之一。
lambda表達式有如下優點
聲明式程式設計風格:就地匿名定義目标函數或函數對象,不需要額外寫一個命名函數或者函數對象。以更直接的方式去寫程式,有好的可讀性和維護性
簡潔:不需要額外再寫一個函數或者函數對象,避免了代碼膨脹和功能分散,讓開發者更加集中精力主手邊的問題,同時也擷取了更高的生産率。
在需要的時間和地點實作功能必報,使程式更靈活
lambda表達式定義了一個匿名函數,并且可以捕獲一定範圍内的變量,其文法形式可歸納為:
[capture] (params)opt->ret {body;};
lambda表達式可以通過捕獲清單捕獲一定範圍内的變量:
[] 不捕獲任何變量
[&] 捕獲外部作用域中所有變量,并作為引用主函數體中使用
[=] 捕獲外部作用域中所有變量,并作為副本在函數體中使用
[=,&foo] 按值捕獲外部作用域中所有變量,并按引用捕獲foo變量
[bar] 按值捕獲bar變量,同時不捕獲其他變量。
[this] 捕獲目前類中的this指針,讓lambda表達式擁有和目前類成員函數同樣的通路權限。如果已經使用了&或者=,就預設添加此選項
例如
auto f=[](int a){ return a+1; }
std::cout << f(1)<<std::endl; //輸出:2
可以看到,上面通過一行代碼定義了一個小小的功能閉包,用來将輸入加1并傳回。
需要注意的是,初始化清單不能用于傳回值的自動推導:
auto x1=[](int i){ return i; }; //OK,return type is int
auto x2={ return {1,2}; }; //error: 無法推導出傳回值類型
另外,lambda表達式在沒有參數清單時,參數清單時可以省略的。是以像下面的寫法都是正确的:
auto f1={ return 1; };
auto f2=[]{ return 1; }; //省略空參數表
一個容易出錯的細節是關于lambda表達式的延遲調用的:
int a=0;
auto f=[=]{ return a; }; //按值捕獲外部變量
a +=1; //a被修改
std::cout<<f()<<std::endl; //輸出0
雖然通過a +=1,a的值取得了變化,但是因為f中存儲的a是按值捕獲的,a還是捕獲時的值,是以仍然為0
下面看一下它的具體用法