這個實現的效果類似於匿名函數,不想C++98/03那樣一個函數所有人都能調用,不公開不必要的接口,提高程序安全性。
首先來寫個最簡單的lambda表達式。
[]{};
對,5個字符就成爲了一個lambda表達式了,雖然並沒卵用,不過至少跨出了一步。這個lambda表達式實際上是精簡後的表達式。不加以精簡的話,原表達式應該像這樣:
[](){};
看起來挺簡單的,我也這麼覺得
解釋下,首先一對方括號代表捕獲列表,含義後面再解釋。然後是一對圓括號,代表lambda函數的參數列表,當參數爲空可省略這對圓括號,就像上面5個字符的lambda表達式這樣。接下來是一對大括號,這個和函數的大括號沒什麼區別了,裏面可以加代碼,可以加return。
下面我們來實現一個lambda表達式,用來計算兩個int數字的和
auto sum = [] (int a, int b) {
return a+b;
};
這兒爲了方便,使用auto自動生成類型。調用方式也簡單,直接 sum(3,5); 就行了,返回的類型爲自動推導類型。關於這個類型,目前我知道的,有兩種形式保存,一種是通過函數指針。這種方式只能對捕獲列表,也就是那對中括號爲空的lambda函數進行保存,代碼如下:
#include <iostream>
using namespace std;
using pSum = int (*)(int, int);//C++11新特性,類型重定義,效果與 typedef int (*pSum)(int, int); 完全相同
int main (int argc, char* argv []) {
pSum sum = [] (int a, int b) {
return a + b;
};
cout << sum (3, 5) << endl;
return 0;
}
結果吶,對你沒猜錯,就是8。接下來就是針對捕獲列表不爲空的情況了,下面說下捕獲列表的作用。捕獲列表是在函數中定義lambda表達式時,用於方便獲取局部變量的值或引用。
#include <iostream>
using namespace std;
int main (int argc, char* argv []) {
int i = 5;
[&i] () { i = 3; }();
cout << i << endl;
return 0;
}
定義lambda後直接調用,直接在lambda函數後面加一對圓括號傳參就行了。這兒我定義了一個變量i,然後通過捕獲列表傳入i的引用,然後對i進行重新賦值。程序運行結果爲3。關於捕獲的引用傳遞與值傳遞的區別是,值傳遞後變量不可更改,引用傳遞後變量可修改。上面我傳的是引用,使用“&i”,值傳遞直接寫個 i 就行了。
這兒可以寫多個引用或值傳遞。如果一次性需要引入所有局部變量,那麼寫個 [&] 代表引用所有,寫個 [=]代表傳遞所有的值。傳值後的變量不可修改,有辦法能加個可修改屬性,如下代碼:
#include <iostream>
using namespace std;
int main (int argc, char* argv []) {
int i = 5;
[i] () mutable { i = 3; }();
cout << i << endl;
return 0;
}
mutable表示可以修改值傳遞的數據,但不影響函數的局部變量。上面這代碼的程序運行結果還是5。那麼這樣的lambda表達式如何存儲呢?這得通過std::function。如下代碼演示如何存放包含捕獲的lambda表達式
#include <iostream>
#include <functional>
using namespace std;
int main (int argc, char* argv []) {
function<int (int, int)> f = [] (int a, int b) { return a + b; };
cout << f (3, 5) << endl;
return 0;
}
計算兩個數字之和的lambda表達式,除了通過函數指針外,也可通過function存儲。這兒沒有寫捕獲列表,寫了也能存儲。