1. 程式人生 > >Lambda 表達式的演示樣例-來源(MSDN)

Lambda 表達式的演示樣例-來源(MSDN)

guid 程序 const acc b16 sent except 代碼片段 catch

本文演示怎樣在你的程序中使用 lambda 表達式。 有關 lambda 表達式的概述。請參閱 C++ 中的 Lambda 表達式。

有關 lambda 表達式結構的具體信息,請參閱 Lambda 表達式語法。

本文內容

聲明 Lambda 表達式

調用 Lambda 表達式

嵌套 Lambda 表達式

高階 Lambda 函數

在函數中使用 Lambda 表達式

配合使用 Lambda 表達式和模板

處理異常

配合使用 Lambda 表達式和托管類型

聲明 Lambda 表達式

技術分享
演示樣例 1

因為 lambda 表達式已類型化,所以你能夠將其指派給 auto 變量或 function 對象。例如以下所看到的:

技術分享代碼

C++
// declaring_lambda_expressions1.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{

    using namespace std;

    // Assign the lambda expression that adds two numbers to an auto variable.
    auto f1 = [](int x, int y) { return x + y; };

    cout << f1(2, 3) << endl;

    // Assign the same lambda expression to a function object.
    function<int(int, int)> f2 = [](int x, int y) { return x + y; };

    cout << f2(3, 4) << endl;
}

技術分享輸出

              <span id="mt5" class="sentence" data-guid="00b907fd343e9d626276b5e4eac3d68a" data-source="" 5"="" style="margin: 0px; padding: 0px;">5
7
            

技術分享備註

有關具體信息。請參閱 自己主動 (C++、function 類和函數調用 (C++)。

盡管 lambda 表達式多在函數的主體中聲明,可是能夠在初始化變量的不論什麽地方聲明。

技術分享演示樣例 2

Visual C++ 編譯器將在聲明而非調用 lambda 表達式時,將表達式綁定到捕獲的變量。

下面演示樣例顯示一個通過值捕獲局部變量 i 並通過引用捕獲局部變量 j 的 lambda 表達式。

因為 lambda 表達式通過值捕獲 i。因此在程序後面部分中又一次指派 i 不影響該表達式的結果。 可是,因為 lambda 表達式通過引用捕獲 j,因此又一次指派 j 會影響該表達式的結果。

技術分享代碼

C++
// declaring_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{
   using namespace std;

   int i = 3;
   int j = 5;

   // The following lambda expression captures i by value and
   // j by reference.
   function<int (void)> f = [i, &j] { return i + j; };

   // Change the values of i and j.
   i = 22;
   j = 44;

   // Call f and print its result.
   cout << f() << endl;
}

技術分享輸出

              47
            

[轉到頁首]

調用 Lambda 表達式

你能夠馬上調用 lambda 表達式,如以下的代碼片段所看到的。 第二個代碼片段演示怎樣將 lambda 作為參數傳遞給標準模板庫 (STL) 算法。比如 find_if

技術分享演示樣例 1

下面演示樣例聲明的 lambda 表達式將返回兩個整數的總和並使用參數 5 和 4 馬上調用該表達式:

技術分享代碼

C++
// calling_lambda_expressions1.cpp
// compile with: /EHsc
#include <iostream>

int main()
{
   using namespace std;
   int n = [] (int x, int y) { return x + y; }(5, 4);
   cout << n << endl;
}

技術分享輸出

              9
            

技術分享演示樣例 2

下面演示樣例將 lambda 表達式作為參數傳遞給 find_if 函數。 假設 lambda 表達式的參數是偶數。則返回 true。

技術分享代碼

C++
// calling_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <list>
#include <algorithm>
#include <iostream>

int main()
{
    using namespace std;

    // Create a list of integers with a few initial elements.
    list<int> numbers;
    numbers.push_back(13);
    numbers.push_back(17);
    numbers.push_back(42);
    numbers.push_back(46);
    numbers.push_back(99);

    // Use the find_if function and a lambda expression to find the 
    // first even number in the list.
    const list<int>::const_iterator result = 
        find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; });

    // Print the result.
    if (result != numbers.end()) {
        cout << "The first even number in the list is " << *result << "." << endl;
    } else {
        cout << "The list contains no even numbers." << endl;
    }
}

技術分享輸出

              列表中的第一個偶數是 42。

技術分享備註

有關 find_if 函數的具體信息,請參閱 find_if。 有關運行公共算法的 STL 函數的具體信息,請參閱 <algorithm>。

[轉到頁首]

嵌套 Lambda 表達式

技術分享演示樣例

你能夠將 lambda 表達式嵌套在還有一個中,例如以下例所看到的。 內部 lambda 表達式將其參數與 2 相乘並返回結果。 外部 lambda 表達式通過其參數調用內部 lambda 表達式並在結果上加 3。

技術分享代碼

C++
// nesting_lambda_expressions.cpp
// compile with: /EHsc /W4
#include <iostream>

int main()
{
    using namespace std;

    // The following lambda expression contains a nested lambda
    // expression.
    int timestwoplusthree = [](int x) { return [](int y) { return y * 2; }(x) + 3; }(5);

    // Print the result.
    cout << timestwoplusthree << endl;
}

技術分享輸出

              13
            

技術分享備註

在該演示樣例中。[](int y) { return y * 2; } 是嵌套的 lambda 表達式。

[轉到頁首]

高階 Lambda 函數

技術分享演示樣例

很多編程語言都支持高階函數的概念。

高階函數是採用還有一個 lambda 表達式作為其參數或返回 lambda 表達式的 lambda 表達式。

你能夠使用 function 類,使得 C++ lambda 表達式具有類似高階函數的行為。 下面演示樣例顯示返回 function 對象的 lambda 表達式和採用 function 對象作為其參數的 lambda 表達式。

技術分享代碼

C++
// higher_order_lambda_expression.cpp
// compile with: /EHsc /W4
#include <iostream>
#include <functional>

int main()
{
    using namespace std;

    // The following code declares a lambda expression that returns 
    // another lambda expression that adds two numbers. 
    // The returned lambda expression captures parameter x by value.
    auto addtwointegers = [](int x) -> function<int(int)> { 
        return [=](int y) { return x + y; }; 
    };

    // The following code declares a lambda expression that takes another
    // lambda expression as its argument.
    // The lambda expression applies the argument z to the function f
    // and multiplies by 2.
    auto higherorder = [](const function<int(int)>& f, int z) { 
        return f(z) * 2; 
    };

    // Call the lambda expression that is bound to higherorder. 
    auto answer = higherorder(addtwointegers(7), 8);

    // Print the result, which is (7+8)*2.
    cout << answer << endl;
}

技術分享輸出

              30
            

[轉到頁首]

在函數中使用 Lambda 表達式

技術分享演示樣例

你能夠在函數的主體中使用 lambda 表達式。 lambda 表達式能夠訪問該封閉函數可訪問的不論什麽函數或數據成員。 你能夠顯式或隱式捕獲 this 指針,以提供對封閉類的函數和數據成員的訪問路徑。

你能夠在函數中顯式使用 this 指針。例如以下所看到的:

C++
void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(), 
      [this](int n) { cout << n * _scale << endl; });
}

你也能夠隱式捕獲 this 指針:

void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(), 
      [=](int n) { cout << n * _scale << endl; });
}

下面演示樣例顯示封裝小數位數值的 Scale 類。

C++
// function_lambda_expression.cpp
// compile with: /EHsc /W4
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

class Scale
{
public:
    // The constructor.
    explicit Scale(int scale) : _scale(scale) {}

    // Prints the product of each element in a vector object 
    // and the scale value to the console.
    void ApplyScale(const vector<int>& v) const
    {
        for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale << endl; });
    }

private:
    int _scale;
};

int main()
{
    vector<int> values;
    values.push_back(1);
    values.push_back(2);
    values.push_back(3);
    values.push_back(4);

    // Create a Scale object that scales elements by 3 and apply
    // it to the vector object. Does not modify the vector.
    Scale s(3);
    s.ApplyScale(values);
}

技術分享輸出

              <span id="mt41" class="sentence" data-guid="099d61fcf3211e322f2ad2aec4bc821f" data-source="" 3"="" style="margin: 0px; padding: 0px;">3
6
9
12

            

技術分享備註

ApplyScale 函數使用 lambda 表達式打印小數位數值與 vector 對象中的每一個元素的乘積。 lambda 表達式隱式捕獲 this 指針,以便訪問 _scale 成員。

[轉到頁首]

配合使用 Lambda 表達式和模板

技術分享演示樣例

因為 lambda 表達式已類型化。因此你能夠將其與 C++ 模板一起使用。 以下的演示樣例顯示 negate_all 和 print_all 函數。

negate_all 函數將一元 operator- 應用於 vector對象中的每一個元素。 print_all 函數將 vector 對象中的每一個元素打印到控制臺。

技術分享代碼

C++
// template_lambda_expression.cpp
// compile with: /EHsc
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

// Negates each element in the vector object. Assumes signed data type.
template <typename T>
void negate_all(vector<T>& v)
{
    for_each(v.begin(), v.end(), [](T& n) { n = -n; });
}

// Prints to the console each element in the vector object.
template <typename T>
void print_all(const vector<T>& v)
{
    for_each(v.begin(), v.end(), [](const T& n) { cout << n << endl; });
}

int main()
{
    // Create a vector of signed integers with a few elements.
    vector<int> v;
    v.push_back(34);
    v.push_back(-43);
    v.push_back(56);

    print_all(v);
    negate_all(v);
    cout << "After negate_all():" << endl;
    print_all(v);
}

技術分享輸出

              <span id="mt49" class="sentence" data-guid="e75e27c52a6284dad516bc98a31bfe72" data-source="" 34"="" style="margin: 0px; padding: 0px;">34
-43
56
After negate_all():
-34
43
-56

            

技術分享備註

有關 C++ 模板的具體信息,請參閱模板。

[轉到頁首]

處理異常

技術分享演示樣例

lambda 表達式的主體遵循結構化異常處理 (SEH) 和 C++ 異常處理的原則。 你能夠在 lambda 表達式主體中處理引發的異常或將異常處理推遲至封閉範圍。

下面演示樣例使用for_each 函數和 lambda 表達式將一個 vector 對象的值填充到還有一個中。

它使用 try/catch 塊處理對第一個矢量的無效訪問。

技術分享代碼

C++
// eh_lambda_expression.cpp
// compile with: /EHsc /W4
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
    // Create a vector that contains 3 elements.
    vector<int> elements(3);

    // Create another vector that contains index values.
    vector<int> indices(3);
    indices[0] = 0;
    indices[1] = -1; // This is not a valid subscript. It will trigger an exception.
    indices[2] = 2;

    // Use the values from the vector of index values to 
    // fill the elements vector. This example uses a 
    // try/catch block to handle invalid access to the 
    // elements vector.
    try
    {
        for_each(indices.begin(), indices.end(), [&](int index) { 
            elements.at(index) = index; 
        });
    }
    catch (const out_of_range& e)
    {
        cerr << "Caught ‘" << e.what() << "‘." << endl;
    };
}

技術分享輸出

              Caught ‘invalid vector<T> subscript‘.
            

技術分享備註

有關異常處理的具體信息,請參閱 Visual C++ 中的異常處理。

[轉到頁首]

配合使用 Lambda 表達式和托管類型 (C++/CLI)

技術分享演示樣例

lambda 表達式的捕獲子句不能包括具有托管類型的變量。 可是。你能夠將具有托管類型的實際參數傳遞到 lambda 表達式的形式參數列表。

下面演示樣例包括一個 lambda 表達式,它通過值捕獲局部非托管變量 ch,並採用 System.String 對象作為其參數。

技術分享代碼

C++
// managed_lambda_expression.cpp
// compile with: /clr
using namespace System;

int main()
{
    char ch = ‘!‘; // a local unmanaged variable

    // The following lambda expression captures local variables
    // by value and takes a managed String object as its parameter.
    [=](String ^s) { 
        Console::WriteLine(s + Convert::ToChar(ch)); 
    }("Hello");
}

技術分享輸出

              Hello!
            

技術分享備註

技術分享

Lambda 表達式的演示樣例-來源(MSDN)