C++開發者的VS2010(二)—— Lambda 表示式
匿名函式是那種沒有函式名但有函式體的函式,很多動態語言都支援匿名函式。在VS2010之前,VC作為一種交低階的語言不支援類似的特性,但是VS2010引入了Lambda表示式,增加了對這個特性的支援。
早在C語言的時代我們就可以使用函式指標來將函式作為一個“物件”看待,後來C++標準庫的出現又引入了函式物件。但是和那些動態語言相比,C++中編寫函式物件的代價還是巨大的,有時候為了實現非常簡單的功能,你需要寫一個類,這樣程式碼量大大增加,而且根據程式閱讀的“區域性性”原則,程式碼閱讀起來也比較費勁。Lambda表示式的引入可謂是C++進步的一大表現,從此我們可以在C++中使用匿名函數了。
先來看一個最簡單的例子。
#include <vector> #include <iostream> #include <algorithm> int _tmain(__in int _Argc, __in LPCTSTR* _Argv) { int i, sum = 0; std::vector<int> vct; for (i = 1; i <= 100; i++) vct.push_back(i); for_each(vct.begin(), vct.end(), [&sum](int n) { // Lambda表示式定義的匿名函式 sum += n; } ); cout << sum << endl; return 0; }
這段程式碼我們用Lambda函式定義了一個匿名函式物件來累加for_each演算法所遍歷的每一個vector中的元素。看起來是不是很簡潔?!
結合上文介紹的auto關鍵字,我們使用Lambda表示式定義了一個匿名函式fun,實現和上面的程式碼一樣的功能。
#include <vector> #include <iostream> #include <algorithm> int _tmain(__in int _Argc, __in LPCTSTR* _Argv) { int i, sum = 0; std::vector<int> vct; // 用Lambda表示式定義一個匿名函式 auto fun = [&sum](int n) { sum += n; }; for (i = 1; i <= 100; i++) vct.push_back(i); for_each(vct.begin(), vct.end(), fun); cout << sum << endl; return 0; }
Lambda表示式的語法為:
[capture-clause] (parameter-list) mutable ->return-type
{
function-body
}
其中,capture-clause表示函式體中需要使用的作用域內的變數的引用或者值,可以為空。上面的程式碼中我引用了作用域內的sum變數,那麼使用了&字首來表達這個需求。如果我想使用sum的值,那麼只要寫成[sum]即可,不需要加&字首。如果我寫成[&sum,i],那麼表示我想引用sum並使用i的值(而不是i的引用)。有幾個需要注意的地方,那麼capture-clause支援[&],和[=],分別表示引用所有可以引用的變數和使用所有可以使用的變數的值,除非後面特別指定(比如[&,i]或者[=,&i])。
parameter-list和普通函式的引數表一樣。
當capture-clause中有使用某個變數的值的時候,有時候需要修改這個值,那麼用mutable關鍵字來修飾。但是不用擔心,對這個值的修改僅僅是修改了它的值的副本,這個類似於函式引數的傳值。下面的程式碼執行後,n的值還是0。
int n = 0;
auto fun = [=]() mutable {
n = 1;
};
fun();
我們知道普通函式可以有返回值也可以沒有,Lambda表示式中也支援。只不過寫法不同,當Lambda表示式中想用返回值,需要使用“->return-type”的形式,比如,
auto fun = [&](int n) ->int {
return n;
};
From: http://jgshining.me/blog/2010/05/c%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84vs2010%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94-lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F/