今日准备着手在C++11多线程编程,在网上找的教程里面看到这么一句话:
“线程函数不仅支持普通函数,还可以是类的成员函数和lambda表达式”
早上在看《C++程序设计语言(第四部分:标准库)》中就看到了N次,原本想先写个示例,等以后有时间在来理解。
没有想到在一次看到了lambda表达式,看来不得不提前准备去理解这个概念了。
从百度百科里面开到lambda表达式的叙述:
【【“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
λ演算,λ(Lambda(大写Λ,小写λ)读音:lan b(m) da(兰亩达)['læ;mdə])演算是一套用于研究函数定义、函数应用和递归的形式系统。它由 Alonzo Church 和 Stephen Cole Kleene 在 20 世纪三十年代引入,Church 运用 lambda 演算在 1936 年给出 判定性问题 (Entscheidungsproblem) 的一个否定的答案。这种演算可以用来清晰地定义什么是一个可计算函数。关于两个 lambda 演算表达式是否等价的命题无法通过一个通用的算法来解决,这是不可判定性能够证明的头一个问题,甚至还在停机问题之先。】】
所以首先它是一个匿名函数,如果仅仅是匿名函数,Java早就有匿名函数这一个概念了。取名lambda是为了解决什么问题呢?
在看后面叙述的, Lambda表达式可以表示一个闭包??嗯,闭包是一个什么概念?
继续百度百科:
【【闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。】】
==>这句话里面重点,闭包是一个函数内部的函数,可以读取它所关联函数的局部变量。
【【闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。】】
==>这里提出了一个编程语言里面的一个新变量->自由变量,作用域在关联函数和匿名函数之间,定义在关联函数中的局部变量叫做自由变量
通过一下的信息查找,了解到了Lambda在编译语言中的特性,以及它所拥有的语言特性。然后我们继续看它在C++11中引入的说明。
C++ Lambda表达式:
ISO C++ 11 标准的一大亮点是引入Lambda表达式。基本语法如下:
[capture list] (parameter list) -> return type { function body }
其中除了“[ ]”(其中捕获列表可以为空)和“复合语句”(相当于具名函数定义的函数体),其它都是可选的。它的类型是单一的具有成员operator()的非联合的类类型,称为闭包类型(closure type)。
C++中,一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。它与普通函数不同的是,lambda必须使用尾置返回来指定返回类型。
例如调用
bool compare(int& a,int& b)
{
return a>b;
}
然后,再这样调用:
sort(a, a+n, compare);
然而,用ISO C++ 11 标准新增的Lambda表达式,可以这么写:
sort(a, a+n, [](int a,int b){return a>b;});//降序排序
这样一来,代码明显简洁多了。
由于Lambda的类型是单一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:
auto f=[](int a,int b){return a>b;};
和其它语言的一个较明显的区别是Lambda和C++的类型系统结合使用,如:
auto f=[x](int a,int b){return a>x;};//x被捕获复制
int x=0, y=1;
auto g=[&](int x){return ++y;};//y被捕获引用,调用g后会修改y,需要注意y的生存期
bool(*fp)(int, int)=[](int a,int b){return a>b;};//不捕获时才可转换为函数指针
其中 [&]
表示以引用的方式捕获所有的外部自动变量。
Lambda表达式可以嵌套使用。
即将出版的ISO C++14支持基于类型推断的泛型lambda表达式。上面的排序代码可以这样写:
sort(a, a+n, [](const auto& a,const auto& b){return a>b;});//降序排序:不依赖a和b的具体类型
因为参数类型和函数模板参数一样可以被推导而无需和具体参数类型耦合,有利于重构代码;和使用auto声明变量的作用类似,它也允许避免书写过于复杂的参数类型。特别地,不需要显式指出参数类型使使用高阶函数变得更加容易。
更多C++11标准的Lambda表达式以及特性可以参考:
http://www.cnblogs.com/coderland/p/5902903.html
http://www.cnblogs.com/haippy/archive/2013/05/31/3111560.html
The C++ Standards Committee
C++11 - the new ISO C++ standard
C++ reference
C++11