不少高級語言裏引入了lambda表達式的概念,即匿名函數。以往C++須要傳入一個函數的時候,必須事先進行聲明,視狀況能夠聲明爲一個普通函數而後傳入函數指針,或者聲明一個funtor,而後傳入一個對象。
但這種傳統方法太過複雜,一個簡單的遍歷輸出就須要聲明一個類或者函數,原本用於簡化語法的東西卻使語法大大複雜化。
好比一個用隨機數填充數組的例子:
#include <iostream>
#include <cstdlib>
#include <iterator>
#include <algorithm>
using namespace std;ios
class mi_randc++
{
�
public:
�
mi_rand (int start_pos, int end_pos)
�
: a(start_pos), b(end_pos)
�
{}express
�
unsigned operator () ()
�
{
�
return rand() % (b-a+1) + a;
�
}ubuntu
�
private:
�
int a, b;
};數組
int main()
{
�
const int SIZE = 20;
�
int array[SIZE];
�
generate_n (array, SIZE, mi_rand (1, 30));
�
�
copy (array, array + SIZE,
�
ostream_iterator<int> (cout, " "));
�
cout << endl;
�
�
return 0;
}
示例中,generate_n的目的是使填充數組的操做簡單化,但爲了這種簡單化卻要額外聲明一個類。輸出數組時利用STL的確能進行語法上的簡化,可是這種簡化卻要求對STL很是瞭解,並且拓展性很是差。
所幸,在c++0x標準中終於引入了lambda表達式,目前 VS 2010 和 g++ 4.5 已經進行了試驗性的實現。針對上面的填充和輸出操做,下面是使用lambda表達式的簡化版:
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;函數
int main()
{
�
const int SIZE = 20;
�
int array[SIZE];
�
generate_n (array, SIZE,
�
[] () { return rand() % 30 + 1; });spa
�
for_each (array, array + SIZE,
�
[] (int a){ cout << a << " "; });
�
�
return 0;
}指針
編譯時須要注意的是,VS要求版本在2010以上,編譯時須要加上 /EHsc 參數。使用g++編譯的話版本要在版本4.5以上,並加上 --std=c++0x 參數。
g++目前(10年八月)的最新版本爲4.51,你能夠到 http://gcc.gnu.org/自行下載編譯。ubuntu下能夠經過 PPA for Ubuntu Toolchain Hackers直接安裝二進制版本。對象
下面將闡述lambda表達式的語法,內容主要參考自 Lambda Expression Syntax。
如圖,lambda表達式由下面幾個部分構成:ci
lambda-introducer (捕獲字段)
lambda-parameter-declaration-list (變量列表)
mutable-specification (捕獲的變量能否修改)
exception-specification (異常設定)
lambda-return-type-clause (返回類型)
compound-statement (函數體)
外部變量的捕獲規則
默認狀況下,即捕獲字段爲 [] 時,lambda表達式是不能訪問任何外部變量的,即表達式的函數體內沒法訪問當前做用域下的變量。
若是要設定表達式可以訪問外部變量,能夠在 [] 內寫入 & 或者 = 加上變量名,其中 & 表示按引用訪問,= 表示按值訪問,變量之間用逗號分隔,好比 [=factor, &total] 表示按值訪問變量 factor,而按引用訪問 total。
不加變量名時表示設置默認捕獲字段,外部變量將按照默認字段獲取,後面在書寫變量名時不加符號表示按默認字段設置,好比下面三條字段都是同一含義:
[&total, factor]
[&, factor]
[=, &total]
參數列表
lambda表達式的參數列表基本和函數的一致,不過有以下限制:
參數列表不能有默認參數
不能是可變參數列表
全部的參數必須有個變量名
若是你不提供 mutable-specification, exception-specification, 以及 lambda-return-type-clause,參數列表是也能夠省略的。以下面的表達式:
int main()
{
�
int x = 4;
�
int y = 5;
�
int z = [=] { return x + y; }();
}
可否修改捕獲的變量
若是在參數列表後加上了 mutable,則表示表達式能夠修改按值捕獲的外部變量的拷貝。
異常設置
和函數同樣,能夠用 throw 來限定表達式可以拋出哪些異常。
返回類型
若是設置返回類型,你須要在類型名前面加上 ->。若是你只有一個返回語句的話,返回類型能夠省略,編譯器將會爲你作出判斷。
函數體
lambda表達式的函數體和普通函數大體相同。
下面是lambda表達式的幾個完整例子:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
�
// Create a vector object with each element set to 1.
�
vector<int> v(elementCount, 1);
�
// These variables hold the previous two elements of the vector.
�
int x = 1;
�
int y = 1;
�
// Assign each element in the vector to the sum of the
�
// previous two elements.
�
generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
�
�
// Generate current value.
�
int n = x + y;
�
// Update previous two values.
�
x = y;
�
y = n;
�
return n;
�
});
�
// Print the contents of the vector.
�
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
�
cout << endl;
�
// Print the local variables x and y.
�
// The values of x and y hold their initial values because
�
// they are captured by value.
�
cout << x << " " << y << endl;
}
#include <functional>
int main()
{
�
// Assign the lambda expression that adds two numbers to an auto variable.
�
auto f1 = [] (int x, int y) { return x + y; };
�
// Assign the same lambda expression to a function object.
�
using namespace std::tr1;
�
function<int (int, int)> f2 = [] (int x, int y) { return x + y; };
}
更多例子請參閱 Examples of Lambda Expressions,本文的數個例子也多來源於此。