Lambda表达式语法
本主题描述的 lambda 表达式的语法。 它提供了一个示例,演示的 lambda 表达式,则这些元素的关联方式的结构元素。
下面的程序与两个 STL 算法中使用 lambda 表达式: generate_n和for_each。 Lambda 表达式出现在调用generate_n函数分配它的一个元素, vector对象前面的两个元素的总和。 Lambda 表达式出现在调用for_each函数将打印元素相同的vector到控制台的对象。
// lambda_structure.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
// Create a vector object with each element set to 1.
vector<int> v(elementCount, 1);
// These variables hold the previous two elements of the vector.
int x = 1;
int y = 1;
// Assign each element in the vector to the sum of the
// previous two elements.
generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
// Print the contents of the vector.
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
// Print the local variables x and y.
// The values of x and y hold their initial values because
// they are captured by value.
cout << x << " " << y << endl;
}
有关详细信息generate_n函数,请参阅generate_n。 有关详细信息for_each函数,请参阅for_each。
以下各节描述的 lambda 表达式以及每个元素与前面的示例中的语法。
Lambda 表达式语法
下面的正式定义显示 BNF 格式,lambda 表达式的语法:
lambda 表达式
: lambda introducer lambda 参数声明自愿复合语句
lambda-introducer
: [lambda-captureopt]
lambda 捕获
: 捕获默认
| 捕获列表
|捕获默认,捕获列表
捕获默认
: &
| =
捕获列表
: 捕获
|捕获列表,捕获
捕获
: 标识符
|&标识符
| this
lambda 参数声明
: (lambda 参数声明列表自愿)可变规范自愿异常规范自愿 lambda 返回类型子句可选
lambda 参数声明列表
: lambda 参数
|lambda 参数,lambda 参数声明列表
lambda 参数
: seq-decl-说明符声明符
lambda 返回类型子句
: ->type-id
下一节介绍了如何语法与中介绍的示例。
Lambda 表达式的属性
下图将映射到该示例的语法。
在图中的标注,如下所示:
lambda introducer (称为捕获子句在本主题后面)
lambda 参数声明列表 (称为 参数列表在本主题后面)
可变规范 (称为 可变规范在本主题后面)
异常规范 (称为 异常规范在本主题后面)
lambda 返回类型子句 (称为 返回类型在本主题后面)
复合语句 (称为 lambda 主体在本主题后面)
以下各节介绍的语法的详细信息。
捕获子句
Lambda 表达式可以访问具有自动存储持续时间和封闭范围中的可访问的任何变量。 捕获子句指定是否将 lambda 表达式的主体通过值或引用访问封闭范围中的变量: 具有 & 符的变量 (&) 前缀的引用,并不具有的变量访问&前缀值的访问。 空捕获子句中, [],指示正文的 lambda 表达式访问封闭范围中的任何变量。
默认捕获模式指定显式指定的捕获变量捕获到通过值或引用。 您可以指定默认的捕获模式 (capture-default在语法) 通过指定&或=捕获子句的第一个元素。 &元素指定除非显式指定,否则将 lambda 表达式的主体的访问通过引用所有捕获的变量。 =元素指定除非显式指定,否则将 lambda 表达式的主体访问值的所有被捕获的变量。 例如,如果 lambda 表达式的主体访问外部变量total的引用和外部变量factor的数值,然后捕获以下子句是等效的:
[&total, factor]
[&, factor]
[=, &total]
您可以使用类方法的主体中的 lambda 表达式。 通过this捕获子句可访问到封闭类的方法和数据成员的指针。 有关如何对类方法中使用 lambda 表达式的示例,请参阅示例: 在该主题中的某个方法中使用 Lambda 表达式Lambda表达式的示例。
参数列表
Lambda 表达式的参数列表与类似的参数列表的函数,但以下情况除外:
参数列表中不能有默认参数。
参数列表中不能有一个可变长度参数列表。
参数列表中不能有未命名的参数。
Lambda 表达式可以采取另一个 lambda 表达式作为其参数。 详细信息,请参阅高序位 Lambda 表达式主题中的Lambda表达式的示例。
Lambda 表达式的参数列表是可选的。 如果未将参数传递到 lambda 表达式,并且未提供,则可以省略的参数列表mutable-specification, exception-specification,和lambda-return-type-clause元素。 下面的示例演示省略的参数列表的 lambda 表达式:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
可变的技术指标
可变规范部分可以修改变量值捕获的 lambda 表达式的主体。 上面的示例使用mutable关键字,以便将 lambda 表达式的主体可以修改其副本的外部变量的x和y,可通过值来捕捉的 lambda 表达式。 由于 lambda 表达式捕获变量x和y的数值,保持它们的值1调用后generate_n。
异常规范
您可以使用throw()异常详细信息,以指示将 lambda 表达式不会引发任何异常。 根据常规的功能,使用 Visual C++ 编译器将生成警告 C4297 如果 lambda 表达式声明throw()异常规范和 lambda 主体引发异常,如下面的示例中所示:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
有关异常规范的详细信息,请参阅异常规范。
Return Type
Lambda 表达式的返回类型一部分类似于普通的方法或函数的返回类型部分。 但是,返回类型后面的参数列表,并且必须包括->的返回类型之前。
如果 lambda 正文包含一个返回语句或 lambda 表达式不会返回一个值,则可以省略 lambda 表达式的返回类型部分。 如果 lambda 主体包含一个返回语句,编译器将 deduces 从返回的表达式的类型的返回类型。 否则,编译器 deduces 返回类型是void。
Lambda 表达式可能产生另一个 lambda 表达式作为它的返回值。 详细信息,请参阅高序位 Lambda 表达式主题中的Lambda表达式的示例。
Lambda 主体
Lambda 正文部分的 lambda 表达式可以包含普通的方法或函数的主体可以包含任何内容。 普通函数和 lambda 表达式的主体可以访问以下类型的变量:
参数
本地声明的变量
类的数据成员 (当在类内声明的)
任何具有静态存储持续时间 (例如,全局变量) 的变量
此外,lambda 表达式可以访问它从封闭范围内捕获的变量。 变量是显式捕获的 lambda 表达式捕获子句中出现。 否则,该变量是隐式地捕获。 Lambda 表达式的正文使用隐式地捕获访问变量的默认捕获模式。
lambda_parameter_list.cpp示例隐式地捕获局部变量x和y的值。 下面的示例包含 lambda 表达式显式捕获该变量的n通过值和隐式地捕获变量m通过引用:
// captures_lambda_expression.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int m = 0, n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;
}
本示例将以下内容显示在控制台:
5
0
因为该变量n被捕获的数值,其值将保持0的 lambda 表达式在调用之后。
尽管 lambda 表达式可以只捕获自动存储持续时间的变量,您可以使用 lambda 表达式的正文中的静态存储持续时间的变量。 下面的示例使用generate函数,lambda 表达式中的每个元素赋值vector对象。 Lambda 表达式修改静态变量来生成的下一个元素的值。
// lambda_static_variable.cpp
// compile with: /c /EHsc
#include <vector>
#include <algorithm>
using namespace std;
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;
// The lambda expression that appears in the following call to
// the generate function modifies and uses the local static
// variable nextValue.
generate(v.begin(), v.end(), [] { return nextValue++; });
}
有关详细信息generate函数,请参阅generate。