什么是lambda表达式,我什么时候应该使用?
C ++ 11中的lambda表达式是什么?我什么时候使用?他们在引入之前无法解决哪种类别的问题?
一些示例和用例将很有用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
C ++ 11中的lambda表达式是什么?我什么时候使用?他们在引入之前无法解决哪种类别的问题?
一些示例和用例将很有用。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(11)
C ++中的lambda被视为“可用功能上”。
是的,从字面上看,您将其定义;使用它;随着父函数范围的完成,lambda函数消失了。
C ++在C ++ 11中介绍了它,每个人都开始像每个可能的地方一样使用它。
可以在此处找到的示例,什么是lambda /cpp/language/lambda
我将描述哪个不是那里的,但对于每个C ++程序员
lambda都不意味着在任何地方使用,每个功能都不能被Lambda代替。与正常功能相比,这也不是最快的。因为它的开销需要由Lambda处理。
在某些情况下,它肯定会有助于减少线路数量。
它基本上可以用于代码部分,该部分可以在一个或多个函数中被调用,并且在其他任何地方都不需要该代码,因此您可以为其创建独立的函数。
以下是Lambda的基本示例,也是背景中发生的情况。
用户代码:
编译如何扩展它:,
因此,您可以看到,使用它时会添加什么样的开销。
因此,在任何地方使用它们不是好主意。
它可以在适用的地方使用。
The lambda's in c++ are treated as "on the go available function".
yes its literally on the go, you define it; use it; and as the parent function scope finishes the lambda function is gone.
c++ introduced it in c++ 11 and everyone started using it like at every possible place.
the example and what is lambda can be find here https://en.cppreference.com/w/cpp/language/lambda
i will describe which is not there but essential to know for every c++ programmer
Lambda is not meant to use everywhere and every function cannot be replaced with lambda. It's also not the fastest one compare to normal function. because it has some overhead which need to be handled by lambda.
it will surely help in reducing number of lines in some cases.
it can be basically used for the section of code, which is getting called in same function one or more time and that piece of code is not needed anywhere else so that you can create standalone function for it.
Below is the basic example of lambda and what happens in background.
User code:
How compile expands it:
so as you can see, what kind of overhead it adds when you use it.
so its not good idea to use them everywhere.
it can be used at places where they are applicable.
好吧,我发现的一种实际用途是减少锅炉板代码。例如:
没有lambda,您可能需要为不同的
bsize
案例做些事情。当然,您可以创建一个函数,但是如果您想限制灵魂用户功能范围内的用法怎么办? Lambda的性质满足了这一要求,我将其用于这种情况。Well, one practical use I've found out is reducing boiler plate code. For example:
Without lambda, you may need to do something for different
bsize
cases. Of course you could create a function but what if you want to limit the usage within the scope of the soul user function? the nature of lambda fulfills this requirement and I use it for that case.C ++ 11引入了lambda表达式,以允许我们编写一个内联函数,该函数可用于
lambda表达式中通常返回类型的简短代码段,由编译器本身评估,我们不需要明确指定该表达式。返回型零件可以被忽略,但是在某些复杂情况下,如条件语句中,编译器无法阐明返回类型,我们需要指定。
输出
lambda表达式可以通过从封闭范围访问变量来具有比普通函数更多的功率。我们可以通过三种方式从封闭范围中捕获外部变量:
用于捕获变量的语法:
带有空捕获子句的lambda只能访问那些本地的变量。
输出:
C++ 11 introduced lambda expression to allow us write an inline function which can be used for short snippets of code
Generally return-type in lambda expression are evaluated by compiler itself and we don’t need to specify that explicitly and -> return-type part can be ignored but in some complex case as in conditional statement, compiler can’t make out the return type and we need to specify that.
Output
A lambda expression can have more power than an ordinary function by having access to variables from the enclosing scope. We can capture external variables from enclosing scope by three ways :
The syntax used for capturing variables :
A lambda with empty capture clause [ ] can access only those variable which are local to it.
Output:
之前(及时)给出的答案仍然缺少对初学者的清晰度。尤其是因为可以定义/调用lambda的不同形式。好吧,也许另一个初学者的答案(没有“知识的诅咒”)可能有助于阐明这些不同的形式。
输出:(
灵感通过)
要解决问题海报的其他问题,显示了一个演示数据,其中数据与lambda一起用作数据处理器函数中的函数参数àlamap():
输出:
有关的更多信息:可以从Stack Overflow的一个创始人(2006)中找到这种减少代码重复的典型用例:
。
顺便说一句:您可以想到lambda表达式,就好像我们在函数中定义了正常的(数学)表达式,在该函数中可以从另一个函数中使用这些表达式(计算)。 Lambda有效地允许这一点甚至更多。
Lambdas和其他技术还有助于减少执行代码更改后的git差异“大小”。引用马丁·克拉科尔(Martin Cracauer)的:
(我知道文章的标题不是关于Lambdas的,而是在文章的中心附近,可以找到一些有用的说明))
The answers given before (in time) are still missing some clarity for the beginner. Especially because of the different forms that a lambda can be defined/invoked. Well, perhaps an answer from another beginner (no 'curse of knowledge') may help clarify these different forms.
Output:
(inspiration got via https://dotnettutorials.net/lesson/lambda-expressions-in-cpp/)
To address the further questions of the question poster, a demonstration is shown where data is used together with lambda as function arguments in a data processor function à la map():
Output:
More information about this typical use case to reduce code repetitions can be found here from one of the founders of stack overflow (2006):
https://www.joelonsoftware.com/2006/08/01/can-your-programming-language-do-this/.
BTW: you could think of a lambda expression as if we had normal (mathematical) expressions defined in a function, where these can be used (computed) from within another function. The lambda effectively allows this and even more.
Lambdas and other techniques also help reduce git diff 'size' upon doing code changes. To quote Martin Cracauer in his introduction to Compile Time Computing:
(I know that the title of the article is not about lambdas, but around the center of the article, some general useful notes can be found)
它解决的一个问题是:代码比lambda更简单,对于使用输出参数函数来初始化const成员
您可以初始化类中的const成员,并通过回馈其输出来设置其值作为输出参数。
One problem it solves: Code simpler than lambda for a call in constructor that uses an output parameter function for initializing a const member
You can initialize a const member of your class, with a call to a function that sets its value by giving back its output as an output parameter.
问题
C ++包含有用的通用功能,例如
std :: for_each
和std :: transform
,这可能非常方便。不幸的是,它们也可能很麻烦,尤其是 fuctor 您想适用是特定功能唯一的。如果您仅在那个特定的地方使用
f
,那么写整个班级只是为了做一些微不足道的事情,一个人似乎过于杀伤。在C ++ 03中,您可能很想写下以下内容,以保持函数本地化:
但是不允许使用
f
不能传递给a 模板 c ++ 03中的功能。新的解决方案
C ++ 11引入lambdas允许您编写一个内联匿名函数来替换
struct f
。对于简单的小示例,这可以更清洁(将所有内容都放在一个地方),并且可能更简单地维护,例如以最简单的形式:lambda函数只是匿名函数的句法糖。
返回类型
在简单的情况下,lambda的返回类型是为您推导的,例如:
但是,当您开始编写更复杂的lambdas时,您会迅速遇到编译器无法推导返回类型的情况,例如:
要解决此问题,允许使用
- >允许明确指定lambda函数的返回类型。 t
:“捕获”变量
到目前为止,除了传递给其中lambda的东西以外,我们还没有使用任何其他内容,但是我们也可以在lambda内使用其他变量。如果要访问其他变量,则可以使用捕获子句(表达式的
[]
),该示例中尚未使用,例如:您可以同时通过参考和值捕获,您可以分别使用
&
= 分别指定:[& epsilon,zeta]
通过参考捕获Epsilon,并通过Value捕获Epsilon [&]
通过参考[=]
捕获lambda中使用的[=,& epsilon]
捕获Epsilon 捕获lambda中使用的所有变量,但通过引用引用的operator()
operator()< /code> IS
。const
默认情况下,默认情况下访问它们时,捕获将为const
的暗示。这具有相同输入的每个调用都会产生相同结果的效果,但是您可以将lambda标记为Mutable
请求所产生的operator()
不是<代码> constThe problem
C++ includes useful generic functions like
std::for_each
andstd::transform
, which can be very handy. Unfortunately they can also be quite cumbersome to use, particularly if the functor you would like to apply is unique to the particular function.If you only use
f
once and in that specific place it seems overkill to be writing a whole class just to do something trivial and one off.In C++03 you might be tempted to write something like the following, to keep the functor local:
however this is not allowed,
f
cannot be passed to a template function in C++03.The new solution
C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the
struct f
. For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form:Lambda functions are just syntactic sugar for anonymous functors.
Return types
In simple cases the return type of the lambda is deduced for you, e.g.:
however when you start to write more complex lambdas you will quickly encounter cases where the return type cannot be deduced by the compiler, e.g.:
To resolve this you are allowed to explicitly specify a return type for a lambda function, using
-> T
:"Capturing" variables
So far we've not used anything other than what was passed to the lambda within it, but we can also use other variables, within the lambda. If you want to access other variables you can use the capture clause (the
[]
of the expression), which has so far been unused in these examples, e.g.:You can capture by both reference and value, which you can specify using
&
and=
respectively:[&epsilon, zeta]
captures epsilon by reference and zeta by value[&]
captures all variables used in the lambda by reference[=]
captures all variables used in the lambda by value[&, epsilon]
captures all variables used in the lambda by reference but captures epsilon by value[=, &epsilon]
captures all variables used in the lambda by value but captures epsilon by referenceThe generated
operator()
isconst
by default, with the implication that captures will beconst
when you access them by default. This has the effect that each call with the same input would produce the same result, however you can mark the lambda asmutable
to request that theoperator()
that is produced is notconst
.什么是lambda表达?
lambda表达式的C ++概念源自lambda演算和功能编程。
lambda是一个未命名的函数(在实际编程中,而不是理论中),对于不可重复使用且不值得命名的代码短图。
在C ++中,最小lambda表达式看起来像:
[]
是捕获列表和{}
函数正文。lambda-expression 的完整语法包括属性,
noexcept
/throw
- 规范,需要clauses等更为复杂。捕获列表
捕获列表定义了从lambda的外部进行功能内部的内容以及如何可用。
它可以是:
[x]
[&amp; x]
[&amp;]
当前中的任何变量[=]
this
,并在lambda[this]
中使成员函数可召唤您可以混合以上在逗号分隔列表中
[x,&amp; y]
。init-captures(C ++ 14)
现在可以使用
=
来初始化捕获列表的元素,该元素称为 init-capture 。这允许重命名变量并通过移动捕获。从标准中获取的一个示例:
一个从Wikipedia中获取的示例,显示了如何使用
std :: Move
:模板参数(C ++ 20)
自C ++ 20以来,Lambda表达式可以具有a < -parameter-list
a href =“ https://eel.is/c++draft/temp.pre#nt:template-parameter-list” rel =“ noreferrer”> template =“ https://eel.is/c++draft/expr.prim.lambda.general#def:generic_lambda” rel =“ noreferrer”>通用lambda /code>带有呼叫操作员模板:
参数列表
“ noreferrer”> parameter -declaration-clause 与任何其他C ++函数相同。
当没有参数时,它可以完全省略,这意味着
[](){}
等效于[] {] {}
。通用lambdas(c ++ 14)
lambdas带有
auto
参数为通用lambda s。auto
等于t
在这里t
是周围范围中某个地方某处的类型模板参数):就像c ++ 20 缩写函数模板:
返回类型(返回类型(可能是推论)
,如果lambda只有一个返回语句,则可以省略返回类型,并且具有隐式类型
electType(return_statement)
。还可以使用落后返回类型语法明确提供返回类型:
改进的返回类型扣除额(C ++ 14)
C ++ 14允许每个函数推导的返回类型,并且不将其限制为表单
返回表达式的功能;
。这也扩展到兰巴斯。默认情况下,将lambda的返回类型推定,好像其返回类型被声明为
auto
。可变的lambda(C ++ 14)
如果lambda标记了可变的(例如
[]()可突变{}
),则允许变异通过值捕获的值。Mutable
表示Lambda类型的调用操作员没有const
限定符。功能主体
a block-statement Lambda实际上被称为。
这成为呼叫操作员的主体。
用例,
由ISO标准福利定义的库从Lambdas重大效益,并提高了几个条的可用性,因为现在用户不必在某些可访问的范围中与小型函子混乱代码。
What is a lambda expression?
The C++ concept of a lambda expression originates in the lambda calculus and functional programming.
A lambda is an unnamed function that is useful (in actual programming, not theory) for short snippets of code that are impossible to reuse and are not worth naming.
In C++, the minimal lambda expression looks like:
[]
is the capture list and{}
the function body.The full syntax for a lambda-expression, including attributes,
noexcept
/throw
-specifications, requires-clauses, etc. is more complex.The capture list
The capture list defines what from the outside of the lambda should be available inside the function body and how.
It can be either:
[x]
[&x]
[&]
[=]
this
and making member functions callable within the lambda[this]
You can mix any of the above in a comma separated list
[x, &y]
.Init-captures (C++14)
An element of the capture list can now be initialized with
=
, which is called init-capture.This allows renaming of variables and to capture by moving. An example taken from the standard:
and one taken from Wikipedia showing how to capture with
std::move
:The template parameters (C++20)
Since C++20, lambda expressions can have a template-parameter-list:
Such a generic lambda is like a non-template
struct
with a call operator template:The parameter list
The parameter-declaration-clause is the same as in any other C++ function.
It can be omitted completely when there are no parameters, meaning that
[](){}
is equivalent to[]{}
.Generic Lambdas (C++14)
Lambdas with an
auto
parameter are generic lambdas.auto
would be equivalent toT
here ifT
were a type template argument somewhere in the surrounding scope):This works just like a C++20 abbreviated function template:
Return type (possibly deduced)
If a lambda has only one return statement, the return type can be omitted and has the implicit type of
decltype(return_statement)
.The return type can also be provided explicitly using trailing return type syntax:
Improved Return Type Deduction (C++14)
C++14 allows deduced return types for every function and does not restrict it to functions of the form
return expression;
. This is also extended to lambdas.By default, the return type of a lambda is deduced as if its return type was declared
auto
.Mutable lambda (C++14)
If a lambda is marked mutable (e.g.
[]() mutable { }
) it is allowed to mutate the values that have been captured by value.mutable
means that the call operator of the lambda's type does not have aconst
qualifier.The function body
A block-statement will be executed when the lambda is actually called.
This becomes the body of the call operator.
Use cases
The library defined by the ISO standard benefits heavily from lambdas and raises the usability several bars as now users don't have to clutter their code with small functors in some accessible scope.
lambda表达式通常用于封装算法,以便可以传递到另一个函数。但是,可以在定义上立即执行lambda :
在功能上等同于此
,使lambda表达式是重构复杂函数的强大工具。您首先将代码部分包裹在lambda函数中,如上所示。然后,可以在每个步骤后通过中间测试逐渐执行显式参数化的过程。将代码块完全参数化后(如删除
&amp;
所示),您可以将代码移至外部位置并使其成为正常功能。同样,您可以根据算法 ...
作为作为作为的一种方法来对程序进行分区的方式,您甚至可能会发现对初始化变量,您甚至可能会发现很有用将lambda表达方式作为参数传递给另一个lambda表达式...
lambda表达式也让您创建名为 ,这可能是避免重复逻辑的便捷方法。当将非平凡函数作为参数传递给另一个函数时,使用命名的lambdas在眼睛上(与匿名的inline lambdas相比)也往往更容易。 注意:不要忘记闭合卷曲括号后的分号。
如果随后的分析揭示了功能对象的显着初始化开销,则可以选择将其重写为正常函数。
Lambda expressions are typically used to encapsulate algorithms so that they can be passed to another function. However, it is possible to execute a lambda immediately upon definition:
is functionally equivalent to
This makes lambda expressions a powerful tool for refactoring complex functions. You start by wrapping a code section in a lambda function as shown above. The process of explicit parameterization can then be performed gradually with intermediate testing after each step. Once you have the code-block fully parameterized (as demonstrated by the removal of the
&
), you can move the code to an external location and make it a normal function.Similarly, you can use lambda expressions to initialize variables based on the result of an algorithm...
As a way of partitioning your program logic, you might even find it useful to pass a lambda expression as an argument to another lambda expression...
Lambda expressions also let you create named nested functions, which can be a convenient way of avoiding duplicate logic. Using named lambdas also tends to be a little easier on the eyes (compared to anonymous inline lambdas) when passing a non-trivial function as a parameter to another function. Note: don't forget the semicolon after the closing curly brace.
If subsequent profiling reveals significant initialization overhead for the function object, you might choose to rewrite this as a normal function.
答案
问:C ++ 11中的lambda表达式是什么?
答:在引擎盖下,它是具有超载 operator()const 的自动化类别的对象。这样的对象称为a 闭合,由编译器创建。
这个“闭合”概念类似于C ++ 11中的“绑定”概念,但是Lambdas通常会生成更多的性能代码。同样,通过封闭(而不是典型功能)呼叫允许完全插入。
问:我什么时候使用?
答:当您想定义“简单而又小的逻辑”并要求编译器从上一个问题中发电。您给编译器一些表达式,您想在
operator()
中。所有其他内容,编译器将为您生成。问:Lambdas在引入之前无法解决哪些类别的问题?
答:Lambdas更像是句法糖(即用于易用性的代码),例如“操作员过载”,而不必为Custom 添加全部功能,减去操作... lambdas ... lambdas将更多的不需要代码行保存,以将1-3行的真实逻辑包装到某些类等上等!一些工程师认为,如果线的数量较小,那么在其中犯错误的机会较小(我也这么认为)。
用法的示例
关于lambdas的额外功能,没有问题。如果您不感兴趣
1,请忽略本节。捕获的值。您可以捕获
1.1。您可以在lambdas中引用
static
存储持续时间的变量。他们都被俘虏了。1.2。您可以使用lambda“按值”捕获值。在这种情况下,捕获的VAR将被复制到函数对象(闭合)。
1.3。您可以通过参考捕获。 &amp; - 在这种情况下,指参考,而不是指针。
1.4。存在表示法以按值或参考
1.5捕获所有非静态VAR。存在符号,以按值或参考捕获所有非静态var,而覆盖特定变量是特定的,要专门为副价值或副参考
示例:
按值捕获所有不静态的var,但通过参考捕获param2
捕获所有不静态的var,逐个参考,而通过值捕获param2
2。返回类型扣除
2.1。如果lambda是一种表达式,则可以推导lambda返回类型。或者,您可以明确指定它。
如果lambda具有多个表达式,则必须通过尾随返回类型来指定返回类型。
同样,类似的语法可以应用于自动功能和成员功能
3。捕获的值。您无法捕获
3.1。您只能捕获局部VAR,而不是对象的成员变量。
4。 conversions
4.1 !! lambda不是函数指针,也不是匿名函数,但是 capture-loss lambdas可以隐式转换为函数指针。
ps
有关lambda语法信息的更多信息可以在编程语言C ++#337,2012-16,5.1.2的工作草案中找到。 lambda表达式,第88页
在C ++中14中添加了一个额外的功能,称为“初始化捕获”。它允许您任意执行关闭数据成员的声明:
Answers
Q: What is a lambda expression in C++11?
A: Under the hood, it is the object of an autogenerated class with an overloaded operator() const. Such an object is called a closure and is created by the compiler.
This 'closure' concept is similar to the 'bind' concept from C++11, but lambdas typically generate more performant code. Also, calls through closures (instead of typical functions) allow full inlining.
Q: When would I use one?
A: When you want to define "simple and small logic" and ask the compiler to perform generation from previous question. You give a compiler some expressions which you want to be inside
operator()
. All the other stuff, the compiler will generate for you.Q: What class of problem do lambdas solve that wasn't possible to solve prior to their introduction?
A: Lambdas are more of a syntactical sugar (i.e., code meant for ease-of-use) like "operator overloading" instead of having to make entire functions for custom add, subtract operations... Lambdas save more lines of unneeded code to wrap 1-3 lines of real logic to some classes, and etc.! Some engineers think that if the number of lines is smaller, then there is a lesser chance to make errors in it (I'm think so too).
Example of usage
Extras about lambdas, not covered by question. Ignore this section if you're not interested
1. Captured values. What you can capture
1.1. You can reference to a variable with
static
storage duration in lambdas. They all are captured.1.2. You can use lambda to capture values "by value". In such case, captured vars will be copied to the function object (closure).
1.3. You can capture by reference. & -- in this context mean reference, not pointers.
1.4. Notation exists to capture all non-static vars by value, or by reference
1.5. Notation exists to capture all non-static vars by value, or by reference, while overriding specific variables to be specifically by-value or by-reference
Examples:
Capture all not-static vars by value, but by reference capture Param2
Capture all not-static vars by reference, but by value capture Param2
2. Return type deduction
2.1. Lambda return type can be deduced if lambda is one expression. Or you can explicitly specify it.
If lambda has more than one expression, then return type must be specified via trailing return type.
Also, similar syntax can be applied to auto functions and member-functions
3. Captured values. What you cannot capture
3.1. You can capture only local vars, not member variables of the object.
4. Сonversions
4.1 !! Lambda is not a function pointer and it is not an anonymous function, but capture-less lambdas can be implicitly converted to a function pointer.
P.s.
More about lambda grammar information can be found in Working draft for Programming Language C++ #337, 2012-01-16, 5.1.2. Lambda Expressions, p.88
In C++14 an extra feature, named as "init capture", has been added. It allows you to arbitrarily perform declaration of closure data members:
lambda函数是您在线创建的匿名函数。它可以捕获变量,如某些人所解释的那样,(例如 http://wwwww.stroustrup.com/c+sstroustrup.com/c+++11faq11faq .html#lambda )但是有一些局限性。例如,如果有这样的回调界面,
则可以在现场编写一个函数,例如在下面使用的函数,
但是您不能这样做:
因为C ++ 11标准中的限制。如果要使用捕获,则必须依靠库和
(或其他某些STL库(例如算法)进行间接获取),然后使用STD ::函数,而不是将正常函数作为类似的参数传递:
A lambda function is an anonymous function that you create in-line. It can capture variables as some have explained, (e.g. http://www.stroustrup.com/C++11FAQ.html#lambda) but there are some limitations. For example, if there's a callback interface like this,
you can write a function on the spot to use it like the one passed to apply below:
But you can't do this:
because of limitations in the C++11 standard. If you want to use captures, you have to rely on the library and
(or some other STL library like algorithm to get it indirectly) and then work with std::function instead of passing normal functions as parameters like this:
lambda表达式
的最佳解释之一是由C ++ bjarne stroustrup的作者提供的,他的书*** *** C ++编程语言***
第11章( isbn-13:978-0321563842) >什么是lambda表达式?
我什么时候可以使用?
他们在引入之前无法解决哪些类别的问题?
在这里我想没有lambda表达的每一个动作都可以在没有它们的情况下解决,但是还有更多代码和更大的复杂性。 lambda表达式这是对您的代码优化的方式,也是使其更具吸引力的一种方式。斯特鲁斯普(Stroustup)悲伤:
通过lambda表达式
或通过功能
,即使
您需要的话,也可以命名
lambda表达式
如下:或假设另一个简单的简单样本
将生成下一步
[]
- 这是捕获列表或lambda介绍器
:如果lambdas
不需要访问其本地环境,我们可以使用它。书籍的报价:
附加
lambda表达式
格式附加参考:
One of the best explanation of
lambda expression
is given from author of C++ Bjarne Stroustrup in his book***The C++ Programming Language***
chapter 11 (ISBN-13: 978-0321563842):What is a lambda expression?
When would I use one?
What class of problem do they solve that wasn't possible prior to their introduction?
Here i guess every action done with lambda expression can be solved without them, but with much more code and much bigger complexity. Lambda expression this is the way of optimization for your code and a way of making it more attractive. As sad by Stroustup :
Some examples
via lambda expression
or via function
or even
if u need u can name
lambda expression
like below:Or assume another simple sample
will generate next
[]
- this is capture list orlambda introducer
: iflambdas
require no access to their local environment we can use it.Quote from book:
Additional
Lambda expression
formatAdditional references: