本文地址:http://www.cnblogs.com/archimedes/p/c11-lambda.html,轉載請注明源地址。
“Lambda 表達式”(lambda expression)是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。Lambda表達式可以表示閉包(注意和數學傳統意義上的不同)。
ISO C++ 11 標准的一大亮點是引入Lambda表達式。基本語法如下:
[capture list] (parameter list) ->return type { function body }
其中除了“[ ]”(其中捕獲列表可以為空)和“復合語句”(相當於具名函數定義的函數體),其它都是可選的。它的類型是唯一的具有成員operator()的非聯合的類類型,稱為閉包類型(closure type)。
C++中,一個lambda表達式表示一個可調用的代碼單元。我們可以將其理解為一個未命名的內聯函數。
它與普通函數不同的是,lambda必須使用尾置返回來指定返回類型。
例如:調用<algorithm>中的std::sort,ISO C++ 98 的寫法是要先寫一個compare函數:
bool compare(int &a, int &b) { return a > b; //降序排序 }
然後,再這樣調用:
sort(a, a + n, compare);
然而,用ISO C++ 11 標准新增的Lambda表達式,可以這麼寫:
sort(a, a + n, [](int a, int b){return a > b;}); //降序排序
這樣一來,代碼明顯簡潔多了。
由於Lambda的類型是唯一的,不能通過類型名來顯式聲明對應的對象,但可以利用auto關鍵字和類型推導:
auto f = [](int a, int b){return a > b;});
和其它語言的一個較明顯的區別是Lambda和C++的類型系統結合使用,如:
autof = [x](int a, int b){return a > x;});//x被捕獲復制 int x = 0,y = 1; auto g = [&](int x){return ++y;});//y被捕獲引用,調用g後會修改y,需要注意y的生存期 bool(*fp)(int, int) = [](int a, int b){return a > b;});//不捕獲時才可轉換為函數指針
Lambda表達式可以嵌套使用。
即將出版的ISO C++14支持基於類型推斷的泛型lambda表達式。上面的排序代碼可以這樣寫:
sort(a, a + n, [](const auto &a, const auto &b){return a > b;});//降序排序:不依賴a和b的具體類型
因為參數類型和函數模板參數一樣可以被推導而無需和具體參數類型耦合,有利於重構代碼;和使用auto聲明變量的作用類似,它也允許避免書寫過於復雜的參數類型。特別地,不需要顯式指出參數類型使使用高階函數變得更加容易。
下面舉一個簡單使用Lambda表達式的例子:
#include<iostream> #include<algorithm> #include<vector> #include<ostream> using namespace std; int main() { vector<int> v; for (int i = 0; i < 10; i++){ v.push_back(i); } for_each(v.begin(), v.end(), [](int n){cout << n << " "; }); cout << endl; return 0; }
Lambda表達式默認的返回類型為void
為了對比,下面使用函數對象實現相同功能的代碼:
#include<iostream> #include<algorithm> #include<vector> #include<ostream> #include<cassert> using namespace std; class LambdaFunctor{ public: void operator()(int n) const{ cout << n << " "; } }; int main() { vector<int> v; for (int i = 0; i < 10; i++){ v.push_back(i); } for_each(v.begin(), v.end(), LambdaFunctor()); cout << endl; return 0; }
對比一下,就會發現使用Lambda表達式要簡潔得多
上面提到的Lambda表達式可以操作所在作用域的變量,這需要通過被稱為“捕獲”的特殊語法來實現,就是通過在[]內列出將要捕獲的“外部”變量列表,這樣在函數體內就可以訪問並操作這些變量。參考下面的代碼:
#include<iostream> #include<algorithm> #include<vector> #include<ostream> #include<cassert> using namespace std; int main() { vector<int> v; for (int i = 0; i < 10; i++){ v.push_back(i); } //使用for_each語句和Lambda表達式來實現對偶元素的計數 int evenCount = 0; for_each(v.begin(), v.end(), [&evenCount](int n){ cout << n; if (n % 2 == 0) { cout << " is even" << endl; evenCount++; } else { cout << " is odd" << endl; } }); cout << "There are " << evenCount << " even numbers in the vector." << endl; getchar(); return 0; }
百度百科
《Visual C++2010權威開發指南》