程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++11裡面的Lambda表達式

C++11裡面的Lambda表達式

編輯:C++入門知識

Lambda Expressions in C++
C++中的Lambda表達式


In Visual C++, a lambda expression—referred to as a lambda—is like an anonymous function that maintains state and can access the variables that are available to the enclosing scope. This article defines what lambdas are, compares them to other programming techniques, describes their advantages, and provides a basic example.

在VC++中,一個lambda表達式——指的是一個lambda(希臘字母)——就像匿名函數一樣,保持狀態並可訪問變量(在作用域(enclosing scope)中有效的)。這篇文章定義了什麼叫做Lambda表達式,將它與其他編程技術相比,描述其優越性並提供了基礎的例子。
About Lambdas
Many programming languages support the concept of an anonymous function, which is a function that has a body, but doesn't have a name. A lambda is a programming technique that's related to anonymous functions. A lambda implicitly defines a function object class and constructs a function object of that class type. For more information about function objects, see Function Objects.

許多編程語言支持匿名函數的概念,匿名函數是有函數體卻沒有名稱的函數。Lambda正是依賴匿名函數的一種新技術。(隱式的)Lambda表達式定義了一個函數類,並以它(函數類)作為函數對象(類實例化對象,詳見百度百科)。預知更多,參考MSDN庫有關Function Objects的介紹。
Function Objects vs. Lambdas
When you write code, you probably use function pointers and function objects to solve problems and perform calculations, especially when you use STL algorithms. Function pointers and function objects have advantages and disadvantages—for example, function pointers have minimal syntactic overhead but do not retain state within a scope, and function objects can maintain state but require the syntactic overhead of a class definition.

A lambda combines the benefits of function pointers and function objects and avoids their disadvantages. Like a function objects, a lambda is flexible and can maintain state, but unlike a function object, its compact syntax doesn't require a class definition. By using lambdas, you can write code that's less cumbersome and less prone to errors than the code for an equivalent function object.

The following examples compare the use of a lambda to the use of a function object. The first example uses a lambda to print to the console whether each element in a vector object is even or odd. The second example uses a function object to accomplish the same task.

當你寫代碼時,你可能會用到函數指針,或函數對象來解決問題或者進行演算,尤其當你用STL algorithms時。函數指針和函數對象(或許可理解為仿函數?)有優缺點——例如,函數指針有最小的句法開銷(?)但不能在作用域中保持狀態(?),而函數對象能夠保持狀態卻需要一個類的定義(相較而言較大的句法開銷)
Lambda表達式融合了他們的優缺點。就像函數對象,Lambda表達式很靈活(於此伴生的是很難理解!!)並可保持狀態,不想函數對象,它完整的句法並不需要類的定義。使用lambda表達式可以讓你的代碼不那麼繁瑣、並減少出錯。
下述幾個例子比較了lambda表達式和函數對象。第一個例子使用了lambda表達式在控制台中輸出了在Vector容器中的元素的奇偶性。第二個采用了函數對象實現了同樣的任務。
Example 1: Using a Lambda
This example uses a lambda that's embedded in the for_each function call to print to the console whether each element in a vector object is even or odd.

這個例子采用了內嵌在for_each函數中的lambda表達式,在控制台中輸出vector中元素的奇偶性。
 

// 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; 

// 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;
}Output
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.

Comments
In the example, the third argument to the for_each function is a lambda. The [&evenCount] part specifies the capture clause of the expression, (int n) specifies the parameter list, and remaining part specifies the body of the expression.

在這個例子中,第三個for_each的參數是一個lambda表達式。所謂[&evenCount]部分,明確說明了分句表達式,(int n)明確說明了一個形參(參數?)列表,剩余部分是表達式的主體。
Example 2: Using a Function Object
Sometimes a lambda would be too unwieldy to extend much further than the previous example. The next example uses a function object instead of a lambda, together with the for_each function, to produce the same results as Example 1. Both examples store the count of even numbers in a vector object. To maintain the state of the operation, the FunctorClass class stores the m_evenCount variable by reference as a member variable. To perform the operation, FunctorClass implements the function-call operator, operator(). The Visual C++ compiler generates code that is comparable in size and performance to the lambda code in Example 1. For a basic problem like the one in this article, the simpler lambda design is probably better than the function-object design. However, if you think that the functionality might require significant expansion in the future, then use a function object design so that code maintenance will be easier.

For more information about the operator(), see Function Call (C++). For more information about the for_eachfunction, see for_each.

有時候lambda表達式過於繁雜(擴充功能)。下一個例子采用了函數對象,同樣使用for_each。都是數vector元素中偶數個數,為保持操作狀態,FunctorClass類保存了m_evenCount變量作為一個成員變量的引用。為實現功能,FunctorClass重載(implement?)了function-call操作符,operator()。VC++編譯器產生了與之相當大小和表現得lambda表達式代碼(例一)。在這個基本問題中,簡易的lambda表達式設計可能比函數對象更好。然而,若你認為functionality(函數性?)可能需要一個明確的擴展,那麼就用函數對象寫代碼,那會簡單些。
欲知operator()和for_each,參考Function Call(C++),for_each,在MSDN庫內有。
[cpp]
// 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; 

// 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;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved