天天看點

lambda表達式

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

下面看一下它的具體用法

繼續閱讀