Lambda 表达式语法
本主题介绍 lambda 表达式的语法。 它演示提供 lambda 表达式的结构元素的示例,这些元素与示例。
Lambda 表达式语法
下面用于定义显示语法,ISO C++11 从标准,lambda 表达式 (项标记下标 选择 是可选的):
lambda-introducer lambda-declarator 选择 compound-statement
进一步失败的组件这些语法如下:
lambda-introducer:
[ lambda-capture 选择 ]
lambda-capture:
capture-default
capture-list
capture-default , capture-list
capture-default:
&
=
capture-list:
capture ... 选择
capture-list , capture ... opt
capture:
identifier
& identifier
this
lambda-declarator:
( parameter-declaration-clause ) mutable 选择
exception-specification 选择 attribute-specifier-seq 选择 trailing-return-type 选择
Visual Studio 支持 C++11 标准 Lambda 表达式语法及其所有 C++11 功能与除了 lambda,以下操作:
要,任何其他类,不会自动生成的构造函数并将不根据标准要求将赋值运算符。 有关 rvalue 引用行为支持的更多信息,请参见 对 C++11 功能的支持(现代 C++)中的 Rvalue References 节。
可选的 attribute-specifier-seq 不支持。
Visual Studio 向 C++11 lambda 功能通过添加以下功能:
无状态是 lambda omni 转换的任意函数使用调用约定的函数的指针。
比 { return expression; } 复杂的主体的 lambda 自动返回这样的类型,只要所有返回语句具有相同的类型。(这在 C++14 标准现在建议的)。
Lambda 表达式的属性
下图将该语法映射到示例。
图中的标注如下所示:
lambda-introducer(在本主题的后面称为“capture 子句”)
lambda declarator(在本主题的后面称为“参数列表”)
mutable(在本主题的后面称为“可变规范”)
exception-specification(在本主题的后面称为“异常规范”)
trailing-return-type(在本主题的后面称为“返回类型”)
compound-statement(在本主题的后面称为“lambda 体”)
以下各节对该语法进行了更详细的说明。
Capture 子句
lambda 表达式是类、构造和函数调用运算符。 如同,在定义类时,决定需要发生的对象捕获变量不受值还是引用或者是否是必需的。 如果 lambda 表达式需要访问局部变量和函数参数,它们需要 捕获。 get 子句 (语法中的lambda-introducer ) 所指定 lambda 表达式的主体是可以访问在封闭范围内的变量通过值或通过引用:包含" &的变量 (&) 为前缀) 没有 & 前缀的引用和变量访问值由访问。
空 capture 子句 [ ] 指示 lambda 表达式的主体不访问封闭范围中的变量。
捕获默认模式指定您未显式指定的获取变量是否捕获通过值或通过引用,如果使用它们。 您可以通过将 & 或 = 指定为 capture 子句的第一个元素来指定默认捕获模式(语法中的 capture-default)。 & 元素指定 lambda 表达式的主体通过引用访问所有捕获的变量,除非您显式地另行指定。 = 元素指定 lambda 表达式的主体通过值访问所有捕获的变量,除非您显式地另行指定。 例如,如果 lambda 表达式的主体通过引用访问外部变量 total 并通过值访问外部变量 factor,那么以下 capture 子句等效:
[&total, factor]
{factor, &total]
[&, factor]
[factor, &]
[=, &total]
[&total, =]
有关使用 capture-default 的一种常见的误会位于范围内的任何变量捕获是否使用 lambda。 事实上并非如此 - 在 lambda 提到的那些变量捕获,则使用 capture-default。
如果捕获子句包括 capture-default&,该 lambda 的 get 子句 capture 的 identifier 不能由 &。 沿着同一行,因此,如果获取子句包括 capture-default (=),该子句获得每个 capture 必须以窗体 & identifier。 标识符或 this 不能多次出现在子句获得。 下面的代码段阐释了一些示例。
struct S { void f(int i); }; void S::f(int i) {
[&, i]{}; // OK
[&, &i]{}; // ERROR: i preceded by & when & is the default
[=, this]{}; // ERROR: this when = is the default
[i, i]{}; // ERROR: i repeated
}
省略号 capture 后跟是 pack 扩展,以下面的示例:variadic 模板
template<class... Args>
void f(Args... args) {
auto x = [args...] { return g(args...); };
x();
}
可以将 lambda 表达式用于类方法的主体中。 将 this 指针传递到 capture 子句以提供对封闭类的方法和数据成员的访问权限。 有关示例演示如何使用类用方法的 lambda 表达式,请参见示例:使用将方法的 Lambda 表达式。主题 Lambda 表达式的示例。
在使用子句获得时,应记住这些,理解和压力,尤其当使用具有多线程时的 lambda:
引用获取可用于修改变量之外,获取值,而无法用于修改变量之外 (变量允许复制修改,从原始的)。
而值获取不会反映更新给变量,则获取引用会反映更新到变量中。
而值获取没有生存期依赖关系,这些依赖关系的引用,获取引入生存期依赖关系,这些依赖关系。
许多这些点在这和相关文章中的代码示例所示。
参数列表
参数列表 (lambda declarator) lambda 表达式中为选项并类似于函数的参数列表。
lambda 表达式可以将另一个 lambda 表达式作为其参数。 有关详细信息,请参阅主题 Lambda 表达式的示例中的“高阶 Lambda 表达式”。
lambda 表达式的参数列表可以是可选的。 可以省略空括号,如果不传递参数到 lambda 表达式,并且 lambda-declarator: 不包含 exception-specification、trailing-return-type、mutable。
可变规范
通常的 lambda 函数调用运算符为 Const 按值,但是,mutable 可以取消此操作。 它不导致变量的数据成员。 可变规范使用 lambda 表达式的主体修改由捕获值的变量。 某些示例本文后面演示了 mutable 关键字的用法。
异常规范
您可以使用 throw() 异常规范来指示 lambda 表达式不会引发任何异常。 与正则函数一样,如果 lambda 表达式声明 throw() 异常规范且 lambda 体引发异常,Visual C++ 编译器将生成警告 C4297,如以下示例所示:
// throw_lambda_expression.cpp
// compile with: /W4 /EHsc
int main() // C4297 expected
{
[]() throw() { throw ; }();
}
返回类型
lambda 表达式的返回类型自动推断,并且,这发生,而无需添加关键字,除非指定 trailing-return-type。auto trailing-return-type 类似于普通方法或函数返回类型的部件。 但是,遵循返回类型参数列表,您必须包括尾部的返回类型关键字 ->,在返回类型。
如果 lambda 体包含单个返回语句或 lambda 表达式不返回值,则可以省略 lambda 表达式的返回类型部分。 如果 lambda 体包含单个返回语句,编译器将从返回表达式的类型推导返回类型。 否则,编译器会将返回类型推导为 void(可能需要显示指明返回类型)。 考虑阐释此原则下面的示例代码段。
auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return{ , }; }; // ERROR: return type is void, deducing
// return type from braced-init-list not valid
lambda 表达式可以生成另一个 lambda 表达式作为其返回值。 有关详细信息,请参阅主题 Lambda 表达式的示例中的“高阶 Lambda 表达式”。
Lambda 体
lambda 表达式主体的 lambda (compound-statement) 中可以包含一般的方法或函数主体所能包含的所有内容。 普通函数和 lambda 表达式的主体均可访问以下变量类型:
参数
本地声明变量
类数据成员 (在声明类和 this 内捕获)
具有静态存储持续时间的任何变量(例如,全局变量)
此外,lambda 表达式可以访问它从封闭范围中捕获的变量。 如果某个变量显示在 lambda 表达式的 capture 子句中,则该变量是显式捕获的。 否则,该变量是隐式捕获的。 lambda 表达式的主体使用默认捕获模式来访问隐式捕获的变量。
以下示例包含通过值显式捕获变量 n 并通过引用隐式捕获变量 m 的 lambda 表达式:
// captures_lambda_expression.cpp
// compile with: /W4 /EHsc
#include <iostream>
using namespace std; int main()
{
int m = ;
int n = ;
[&, n] (int a) mutable { m = ++n + a; }();
cout << m << endl << n << endl;
}
本示例将以下内容输出到控制台:
由于变量 n 是通过值捕获的,因此在调用 lambda 表达式后,变量的值仍保持 0 不变。 指定 mutable 允许 n 是在 lambda 中修改。
尽管 lambda 表达式只能捕获具有自动存储持续时间的变量,但您可以在 lambda 表达式的主体中使用具有静态存储持续时间的变量。 以下示例使用 generate 函数和 lambda 表达式为 vector 对象中的每个元素赋值。 lambda 表达式将修改静态变量以生成下一个元素的值。
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = ; // 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++; });
//WARNING: this is not thread-safe and is shown for illustration only
}
有关 generate 函数的详细信息,请参阅 生成。
下面的代码示例使用从前面的函数,并将该表达式的 lambda 表达式的示例与 STL generate_n的算法。 该 lambda 表达式分配的 vector 对象的元素。前两个元素的和的。 改用 mutable 关键字,这样 lambda 表达式体才能改变其外部变量 x 和 y的复制,lambda 表达式按值捕获。 由于 lambda 表达式按值捕获原始变量 x 和 y,它们的值保持为 1,在 lambda 后执行。
// compile with: /W4 /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
#include <string> using namespace std; template <typename C> void print(const string& s, const C& c) {
cout << s; for (const auto& e : c) {
cout << e << " ";
} cout << endl;
} void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = ; // 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++; });
//WARNING: this is not thread-safe and is shown for illustration only
} int main()
{
// The number of elements in the vector.
const int elementCount = ; // Create a vector object with each element set to 1.
vector<int> v(elementCount, ); // These variables hold the previous two elements of the vector.
int x = ;
int y = ; // Sets each element in the vector to the sum of the
// previous two elements.
generate_n(v.begin() + ,
elementCount - ,
[=]() mutable throw() -> int { // lambda is the 3rd parameter
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
print("vector v after call to generate_n() with lambda: ", v); // 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: " << x << " y: " << y << endl; // Fill the vector with a sequence of numbers
fillVector(v);
print("vector v after 1st call to fillVector(): ", v);
// Fill the vector with the next sequence of numbers
fillVector(v);
print("vector v after 2nd call to fillVector(): ", v);
}
vector v after call to generate_n() with lambda:
x: y:
vector v after 1st call to fillVector():
vector v after 2nd call to fillVector():
Lambda 表达式语法的更多相关文章
- Java8初体验(一)lambda表达式语法
感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解 ...
- Java8 lambda表达式语法 1
本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解偏差的地方,希望大家帮忙指出,我会持续修改和优化.本文是该系列的第一篇, ...
- Java8初体验(1):lambda表达式语法
原文出处: 一冰_天锦 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解偏差的地方,希望大家帮忙指出,我会持续修改和优化 ...
- Lambda表达式语法
基础语法:‘->’Lambda操作符* 左侧:Lambda表达式的参数列表 对应接口中方法中的参数列表中的参数(比如nice1中MyPredict这个接口中的方法)* 右侧:Lambda表达式中 ...
- java8【一、lambda表达式语法】
特点 lambda表达式允许将函数作为方法的参数 lambda表达式更加简洁 特征 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需 ...
- Lambda表达式语法进一步巩固
上一次已经初步使用到了Lambda表达式了,这次再次对它的语法进行一下巩固,因为它实在是太重要的,所以多花时间彻底理解它是非常有必要的. 在"Java8 in Action"一书中 ...
- JDK8--03:lambda表达式语法
对于lambda表达式的基础语法,一个是要了解lambda表达式的基础语法,另外一个是需要了解函数式接口 一.lambda表达式基础语法描述 java8中引入了新的操作符 -> ,可以称为l ...
- Lambda表达式语法2
package airycode_java8.nice3; import airycode_java8.nice1.Employee; import org.junit.Test; import ja ...
- Lambda表达式的语法与如何使用Lambda表达式
Lambda表达式是对象,是一个函数式接口的实例 如何来写Lambda表达式? 看参数 看返回值 代码实例1: package day2; import jdk.nashorn.internal.co ...
随机推荐
- Date()对象的设置与解析
怎么获取当前时间? 怎么给Date对象设置特定时间? 将Date对象解析为毫秒数? 将Date对象解析为日月年?获取小时/分钟/秒? 直接new Date()新建对象,可以获取当前时间的Date对象: ...
- JSON学习笔记-1
1.什么是JSON? JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一 ...
- JS + jQuery 实现元素自动滚动到底部,兼容IE、FF、Chrome
HTML代码: <ul class="tasklog-dialog-ul" id="auto_to_bottom"> <li>删除虚拟机 ...
- C# 实现水印
直接上源码 public class WaterTextBox : TextBox { //private const int EM_SETCUEBANNER = 0x1501; //[DllImpo ...
- 用以替换系统NSLog的YouXianMingLog
用以替换系统NSLog的YouXianMingLog 这是本人自己使用并改良的用以替换系统NSLog的类,非常好用,以下是使用示例,现在开源出来并提供源码,好用的话顶一下吧^_^ 效果: YouXia ...
- Go语言-windows安装配置篇
Go-windows安装配置 前言 学习完了python基础,顺便也要提前学习一下go啦,抱着这样的心情,今晚尝试了安装一下go,很顺利的完成了,没有难度. 需要了解更多的关于Go的基本信息可以去维基 ...
- TITLE: BizTalk Server 2013 Administration Console
TITLE: BizTalk Server 2013 Administration Console------------------------------ Could not store tran ...
- November 8th 2016 Week 46th Tuesday
When he can't, he tries a new way to share a new pair. 当他做不到时,他尝试一种新的方式:分享. To share, your failing e ...
- PAT 1001A+B Format
Github 1001 题目速览 1.解题的思路过程 认真读题,题目为A+BFormat,简单的计算a+b问题,特殊在于输出的形式. 输入形式为每个输入文件包含一个测试样例,每个测试样例仅包含一对整型 ...
- 以太坊系列之一: 以太坊RLP用法-以太坊源码学习
RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式.RLP的唯一目标就是解决结构体的编码问题:对原子数据类型(比如,字符串,整数型, ...