首页 > 代码库 > Lambda 表达式的演示样例-来源(MSDN)

Lambda 表达式的演示样例-来源(MSDN)

本文演示怎样在你的程序中使用 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)