表达式无疑是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!开始

auto func = [] { cout << "Hello, World!" << endl; } ();

func();// 调用函数输出Hello, World!

我们可以像创建变量一样方便的创建函数!使用STL我们会为了某个很简单的实现不得不实现一个一个的小函数,的引入可以让我们写出更紧凑的代码:

bool compare(int i,int j) { return (i>j); }
vector<int> v;
// using default comparison (operator <):
std::sort (v.begin(), v.end()); // using function as comp
std::sort (v.begin(), v.end(), compare); // using lambda
std::sort (v.begin(), v.end(), [](int i, int j){ return i > j; }); // Print the contents of the vector.
std::for_each(v.begin(), v.end(), [](int i) { cout << i << " "; }); // C++11 style: using begin(v) instead of v.begin() std::for_each(begin(v), end(v), [](int i) { cout << i << " "; });

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

for( auto d : myvector ) {
cout<< d <<" ";
}

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

// C++98/03: 直接编写一个循环 (使用std::find_if会非常困难)
vector<int>::iterator i = v.begin();
for( ; i != v.end(); ++i ) {
if( *i > x && *i < y ) break;
} // C++11: use std::find_if
auto i = find_if( begin(v), end(v), [=](int i) { return i > x && i < y; } );

数组求和:

for_each(begin(v), end(v), [&](int n){ sum += n;)}

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

// The number of elements in the vector.
const int elementCount = 9;
// 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(begin(v) + 2, elementCount - 2, [=]() mutable throw() -> int {
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});

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

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表达式。

// compile with: /EHsc
#include <functional>
// 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 g = [](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 adds 1.
auto h = [](const function<int (int)>& f, int z) { return f(z) + 1; }; // Call the lambda expression that is bound to h.
auto a = h(g(7), 8);

最后一个问题, what's the type of a lambda expression? 使用C++11增强的各类function的wrapper std::function, 下面是使用作为代理(Delegate)的例子,仅仅是例子,不要问为什么要这样用:)

#include <functional>

class EmailProcessor
{
public:
void receiveMessage (const std::string& message)
{
if ( _handler_func )
{
_handler_func( message );
}
// other processing
}
void setHandlerFunc (std::function<void (const std::string&)> handler_func)
{
_handler_func = handler_func;
} private:
std::function<void (const std::string&)> _handler_func;
}; //当收到Message时,我们希望有个回调函数能够处理 class MessageSizeStore
{
MessageSizeStore () : _max_size( 0 ) {}
void checkMessage (const std::string& message )
{
const int size = message.length();
if ( size > _max_size )
{
_max_size = size;
}
}
int getSize ()
{
return _max_size;
} private:
int _max_size;
}; //我们希望每次Message到来时,统计出历史的最大长度(好无聊啊。。。) EmailProcessor processor;
MessageSizeStore size_store;
processor.setHandlerFunc(
[&] (const std::string& message) { size_store.checkMessage( message ); }
);

引用:



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

C++闭包: Lambda Functions in C++11的更多相关文章

  1. lambda的使用ret = filter(lambda x : x > 22 ,[11,22,33,44])

    #!/usr/bin/env python #def f1(x) : # return x > 22 ret = filter(lambda x : x > 22 ,[11,22,33,4 ...

  2. C++11的闭包(lambda、function、bind)

    c++11开始支持闭包,闭包:与函数A调用函数B相比较,闭包中函数A调用函数B,可以不通过函数A给函数B传递函数参数,而使函数B可以访问函数A的上下文环境才可见(函数A可直接访问到)的变量:比如: 函 ...

  3. C++ 仿函数/函数指针/闭包lambda

    在上一篇文章中介绍了C++11新引入的lambda表达式(C++支持闭包的实现),现在我们看一下lambda的出现对于我们编程习惯的影响,毕竟,C++11历经10年磨砺,出140新feature,对于 ...

  4. Python: Lambda Functions

    1. 作用 快速创建匿名单行最小函数,对数据进行简单处理, 常常与 map(), reduce(), filter() 联合使用. 2. 与一般函数的不同 >>> def f (x) ...

  5. J2SE 8的Lambda --- functions

    functions //1. Runnable 输入参数:无 返回类型void new Thread(() -> System.out.println("In Java8!" ...

  6. C++11 并发指南一(C++11 多线程初探)

    引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...

  7. C++11 并发指南一(C++11 多线程初探)(转)

    引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...

  8. 【C/C++开发】C++11 并发指南一(C++11 多线程初探)

    引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...

  9. 学习C++11的一些思考和心得(1):lambda,function,bind和委托

     1.lambda表达式 lanbda表达式简单地来讲就是一个匿名函数,就是没有名称的函数,如果以前有接触过python或者erlang的人都比较熟悉这个,这个可以很方便地和STL里面的算法配合 st ...

随机推荐

  1. python学习之路网络编程篇(第四篇)

    python学习之路网络编程篇(第四篇) 内容待补充

  2. 02Vue2.0+生命周期

    Vue生命周期是Vue对象从无到有再到无的一个过程,我们又是不仅要明白一个对象的使用, 同时也要知道一个对象怎么创建了,就比如Spring的生命周期,往往不只是面试官的考点, 同时在项目中也也可能常常 ...

  3. WSGI及gunicorn指北(一)

    作为一个Python Web 开发工程师,pyg0每天都喜滋滋的写着基于各种web框架的业务代码. 突然有一天,技术老大过来跟pyg0说,嘿,我们要新上线一个服务,你来帮我部署一下吧.不用太复杂.用g ...

  4. day06_JDBC学习笔记

    ============================================================ 一.JDBC概述 为什么要使用JDBC? JDBC:Java DataBase ...

  5. 使用GDAL进行RPC坐标转换

    使用GDAL进行RPC坐标转换 对于高分辨率遥感卫星数据而言,目前几乎都提供了有理函数模型(RFM)来进行图像校正(SPOT系列提供了有理函数模型之外还提供了严格轨道模型).对遥感影像进行校正目前最常 ...

  6. Unity UGUI图文混排(六) -- 超链接

    图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的. 博主已经将超 ...

  7. Velocity 语法及其在springMVC中的配置

    强烈推荐具体的整合博客:http://blog.csdn.net/duqi_2009/article/details/47752169 整合文章中有几处问题: xml中配置的vm视图解析器,应该按照本 ...

  8. Android中Snackbar的介绍以及使用

    Android中Snackbar的介绍以及使用 介绍 Snackbar可以说是Toast的升级版,不仅有显示信息的功能,还可以添加一个Action,实现点击功能,可以右滑删除. 效果图 Snackba ...

  9. Dynamics CRM2016 Web API之更新记录的单个属性字段值

    在web api中提供了对单个属性的更新接口,这和查询中查询单个属性类似,对这个接口我个人也是比较喜欢的. var id = "{D1E50347-86EB-E511-9414-ADA183 ...

  10. [ExtJS5学习笔记]第二十七节 CMD打包错误 Error C2009: YUI Parse Error (identifier is a reserved word => debugger;)

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/41242993 本文作者:sushengmiyan ------------------ ...