Lambda表達式

不少高級語言裏引入了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,本文的數個例子也多來源於此。

相關文章
相關標籤/搜索