天天看点

C++闭包: Lambda Functions in C++11

C++闭包: Lambda Functions in C++11

表达式无疑是c++11最激动人心的特性之一!它会使你编写的代码变得更优雅、更快速! 它实现了c++11对于支持闭包的支持。首先我们先看一下什么叫做闭包

维基百科上,对于闭包的解释是:

in

programming languages, a closure (also lexical closure orfunction closure) is afunction

or reference to a function together with a referencing environment—a table storing areference to each

of the

non-local variables (also called

free variables or upvalues) of that function.[1] a closure—unlike

a plainfunction pointer—allows a function to access those non-local variables even when invoked outside its immediatelexical

scope.

the concept of closures was developed in the 1960s and was first fully implemented in 1975[citation

needed] as a language feature in the

scheme programming language to support lexically scoped

first-class functions. the use of closures is associated with

functional programming languages such as

lisp and

ml, as traditional imperative languages such as

algol,

c and

pascal do not support returning

nested functions as results from

higher-order functions and thus do not require supporting closures either. many moderngarbage-collected

imperative languages support closures, such as

smalltalk (the first object-oriented language to do so)[2],javascript

and

c#.

简单来说,闭包(closure)是词法闭包(lexical closure)或者函数闭包的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

在程序设计语言中,变量可以分为自由变量(free variable)与约束变量(bound variable)两种。简单来说,一个函数里局部变量和参数都被认为是约束变量;而不是约束变量的则是自由变量。

百度百科的解释可能更加通俗易懂:

闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在 scala、scheme、common lisp、smalltalk、groovy、javascript、ruby、

python和lua,objective c 等语言中都能找到对闭包不同程度的支持。

在编程领域我们可以通俗的说:子函数可以使用父函数中的局部变量,这种行为就叫做闭包!

还是上code吧:还是从hello, world!开始

我们可以像创建变量一样方便的创建函数!使用stl我们会为了某个很简单的实现不得不实现一个一个的小函数,

C++闭包: Lambda Functions in C++11

的引入可以让我们写出更紧凑的代码:

仅仅通过sort和对于vector的遍历,我们就可以看到a lambda的巨大威力。当然了,对于c++11,我们可以使用“现代风格”进行数组的遍历:

另外一个快速示例:找到v里面大于x并且小于y的第一个元素。在c++11中,最简单和干净的代码就是调用一个标准函数。

数组求和:

最后一个使得代码高效优雅的例子:

下面对

C++闭包: Lambda Functions in C++11

表达式语法进行详细的阐述:

C++闭包: Lambda Functions in C++11

1. lambda-introducer: 定义引用自由变量的方式。

    [] // 没有定义任何变量。使用未定义变量会导致错误。

    [x, &y] // x 以传值方式传入(默认),y 以引用方式传入。

    [&] // 任何被使用到的外部变量皆隐式地以引用方式加以使用。

    [=] // 任何被使用到的外部变量皆隐式地以传值方式加以使用。

    [&, x] // x 显示地以传值方式加以使用。其余变量以引用方式加以使用。

    [=, &z] // z 显示地以引用方式加以使用。其余变量以传值方式加以使用。

2. lambda-parameter-declaration-list: 参数列表。但是参数不可以有默认值,不可以使用变长参数,不可以有unamed arguments

3. mutable-specification :使得传值引入的变量可以修改。这个修改因为是修改的外部变量的拷贝,因此并不会影响它本来的值

4. exception-specification:throw()该函数不能抛出异常。如果抛出异常,编译器将报warning c4297。 throw(...) 可以抛出异常。throw(type)可以抛出type的异常

5. lambda-return-type-clause:如果仅有0/1个return的话可以省略。返回值可以是lambda表达式。

最后一个问题, what's the type of a lambda expression? 使用c++11增强的各类function的wrapper std::function, 下面是使用

C++闭包: Lambda Functions in C++11

作为代理(delegate)的例子,仅仅是例子,不要问为什么要这样用:)

引用:

http://www.cprogramming.com/c++11/c++11-lambda-closures.html

http://rednaxelafx.iteye.com/blog/184199

http://www.cplusplus.com/reference/algorithm/sort/

lambda expression syntax

http://msdn.microsoft.com/en-us/library/46h7chx6.aspx

http://msdn.microsoft.com/en-us/library/dd293599.aspx#higherorder