在 C++ 中使用 lambda 運算式

在 Visual C++ 中, Lambda 運算式所參考的方式有二,一是 Lambda與維護狀態的匿名函式,也可以存取封閉範圍可用的變數。本文定義什麼是 Lambda,與其他程式設計技術進行比較,描述它們的優點,並提供基本範例。

如需 Lambda

許多程式語言支援 匿名函式的概念,是函式具有主體,不過,沒有名稱。Lambda 與匿名函式相關的程式設計技巧。Lambda 會暗自定義一個函式物件類別和建構函式物件該類別型別。如需函式物件的詳細資訊,請參閱 函式物件

重要事項重要事項

在沒有在下列 Common Language Runtime (CLR) Managed 實體中支援: ref class、 ref struct、 value class或 value struct。

函式物件對. Lambda

當您撰寫程式碼時,您可能使用函式指標或函式物件解決問題和執行計算,,尤其是在使用 STL 演算法。時。函式指標或函式物件的好處,而缺點。例如,函式指標有最小的語法額外負荷,但是不會保留在範圍內的狀態,因此,函式物件可以維護狀態,但是需要類別定義的語法額外負荷。

Lambda 合併函式指標或函式物件的優點並避免其缺點。像函式物件, Lambda 具有彈性,並可以維護狀態,不過,不同於函式物件,它的精簡語法不需要類別定義。使用 Lambda,您可以為對等函式物件撰寫的程式碼較不麻煩而且比較不容易發生錯誤的程式碼。

下列範例使用函式物件比較使用 Lambda。第一個範例會使用 Lambda 列印到主控台在 vector 物件中的每個項目是否為偶數或奇數。第二個範例會使用函式物件完成相同的工作。

範例 1:使用 Lambda

這個範例會使用 for_each 函式呼叫內嵌列印到主控台的 Lambda 在 vector 物件中的每個項目是否為偶數或奇數。

Dd293608.collapse_all(zh-tw,VS.110).gif程式碼

// even_lambda.cpp
// compile with: cl /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() 
{
   // Create a vector object that contains 10 elements.
   vector<int> v;
   for (int i = 0; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by 
   // using the for_each function and a 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;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

Dd293608.collapse_all(zh-tw,VS.110).gifOutput

0 is even
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 5 even numbers in the vector.

Dd293608.collapse_all(zh-tw,VS.110).gif註解

在此範例中, for_each 函式的第三個引數是 Lambda。[&evenCount] 組件指定運算式的擷取子句, (int n) 指定參數清單,因此,其餘部分指定運算式的主體。

範例 2:使用函式物件

有時候 Lambda 比先前太麻煩而無法擴充進一步。下一個範例使用函式物件而不是 Lambda,使用 for_each 函式時,會產生和的結果範例 1. 相同。這兩個範例都會儲存在 vector 物件中的偶數計數。若要維護作業的狀態, FunctorClass 類別以傳址方式儲存 m_evenCount 變數做為成員變數。若要執行此作業,實作 FunctorClass 函式呼叫運算子, operator()。Visual C++ 編譯器會產生程式碼與範例 1. 中 Lambda 程式碼大小可以比較的和效能。若為基礎問題比函式物件設計請該在本文中,更簡單 Lambda 設計可能好。不過,因此,如果您認為功能可能會在未來需要大量展開,然後使用一個函式物件設計,讓程式碼維護會比較容易。

如需 operator() 的詳細資訊,請參閱函式呼叫 (C++)。如需 for_each 函式的詳細資訊,請參閱 for_each

Dd293608.collapse_all(zh-tw,VS.110).gif程式碼

// even_functor.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class FunctorClass
{
public:
    // The required constructor for this example.
    explicit FunctorClass(int& evenCount) 
        : m_evenCount(evenCount)
    {
    }

    // The function-call operator prints whether the number is
    // even or odd. If the number is even, this method updates
    // the counter.
    void operator()(int n) const
    {
        cout << n;

        if (n % 2 == 0) {
            cout << " is even " << endl;
            ++m_evenCount;
        } else {
            cout << " is odd " << endl;
        }
    }

private:
    // Default assignment operator to silence warning C4512.
    FunctorClass& operator=(const FunctorClass&);

    int& m_evenCount; // the number of even variables in the vector.
};


int main() 
{
    // Create a vector object that contains 10 elements.
    vector<int> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(i);
    }

    // Count the number of even numbers in the vector by 
    // using the for_each function and a function object.
    int evenCount = 0;
    for_each(v.begin(), v.end(), FunctorClass(evenCount));

    // Print the count of even numbers to the console.
    cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

摘要

Lambdas 強大且明確達意的程式設計技巧。若要了解 Lambda 的部分和屬性,請參閱 Lambda 運算式語法。若要了解如何使用 Lambda 在您的程式,請參閱 Lambda 運算式的範例

請參閱

參考

函式呼叫 (C++)

for_each

概念

函式物件

其他資源

C + + 語言參考