Lambda 表达式的示例

 

若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档

本文演示如何在你的程序中使用 lambda 表达式。 有关 lambda 表达式的概述,请参阅 lambda 表达式。 有关 lambda 表达式结构的详细信息,请参阅 Lambda 表达式语法

声明 Lambda 表达式

调用 Lambda 表达式

嵌套 Lambda 表达式

高阶 Lambda 函数

在函数中使用 Lambda 表达式

配合使用 Lambda 表达式和模板

处理异常

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

示例 1

由于 lambda 表达式已类型化,所以你可以将其指派给 auto 变量或 function 对象,如下所示:

代码

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

输出

5
7

备注

有关详细信息,请参阅 autofunction 类函数调用

虽然 lambda 表达式多在函数的主体中声明,但是可以在初始化变量的任何地方声明。

示例 2

Visual C++ 编译器将在声明而非调用 lambda 表达式时,将表达式绑定到捕获的变量。 以下示例显示一个通过值捕获局部变量 i 并通过引用捕获局部变量 j 的 lambda 表达式。 由于 lambda 表达式通过值捕获 i,因此在程序后面部分中重新指派 i 不影响该表达式的结果。 但是,由于 lambda 表达式通过引用捕获 j,因此重新指派 j 会影响该表达式的结果。

代码

// 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 作为参数传递给标准模板库 (STL) 算法,例如 find_if

示例 1

以下示例声明的 lambda 表达式将返回两个整数的总和并使用参数 54 立即调用该表达式:

代码

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

代码

// 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 表达式将其参数与 2 相乘并返回结果。 外部 lambda 表达式通过其参数调用内部 lambda 表达式并在结果上加 3。

代码

// 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 表达式。 你可以使用 function 类,使得 C++ lambda 表达式具有类似高阶函数的行为。 以下示例显示返回 function 对象的 lambda 表达式和采用 function 对象作为其参数的 lambda 表达式。

代码

// 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 表达式可以访问该封闭函数可访问的任何函数或数据成员。 你可以显式或隐式捕获 this 指针,以提供对封闭类的函数和数据成员的访问路径。

你可以在函数中显式使用 this 指针,如下所示:

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 类。

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

输出

3
6
9
12

备注

ApplyScale 函数使用 lambda 表达式打印小数位数值与 vector 对象中的每个元素的乘积。 lambda 表达式隐式捕获 this 指针,以便访问 _scale 成员。

[本文内容]

示例

由于 lambda 表达式已类型化,因此你可以将其与 C++ 模板一起使用。 下面的示例显示 negate_allprint_all 函数。 negate_all 函数将一元 operator- 应用于 vector 对象中的每个元素。 print_all 函数将 vector 对象中的每个元素打印到控制台。

代码

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

输出

34
-43
56
After negate_all():
-34
43
-56

备注

有关 C++ 模板的详细信息,请参阅模板

[本文内容]

示例

lambda 表达式的主体遵循结构化异常处理 (SEH) 和 C++ 异常处理的原则。 你可以在 lambda 表达式主体中处理引发的异常或将异常处理推迟至封闭范围。 以下示例使用 for_each 函数和 lambda 表达式将一个 vector 对象的值填充到另一个中。 它使用 try/catch 块处理对第一个矢量的无效访问。

代码

// 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'.

备注

有关异常处理的详细信息,请参阅 异常处理

[本文内容]

示例

lambda 表达式的捕获子句不能包含具有托管类型的变量。 但是,你可以将具有托管类型的实际参数传递到 lambda 表达式的形式参数列表。 以下示例包含一个 lambda 表达式,它通过值捕获局部非托管变量 ch,并采用 System.String 对象作为其参数。

代码

// 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 表达式和 STL/CLR 库。 有关详细信息,请参阅 STL/CLR 库

System_CAPS_ICON_important.jpg 重要事项

以下公共语言运行时 (CLR) 托管实体中不支持 Lambda:ref classref structvalue classvalue struct

[本文内容]

lambda 表达式
Lambda 表达式语法
auto
function 类
find_if
<algorithm>
函数调用
模板
异常处理
STL/CLR 库

显示: