概念
lambda表达式:是一种表达式,是源代码的组成部分 闭包:是lambda表达式创建的运行期对象,根据不同的捕获模式,闭包会持有数据的副本或引用 闭包类:用于实例化闭包的类,每个lambda表达式都会触发编译器生成一个独一无二的闭包类,而lambda中的语句会变成他的闭包类成员函数的可执行指令
避免默认捕获模式
C++11有两种默认捕获模式:按引用或者按值捕获,按引用的默认捕获方式可能导致空悬引用,按值的默认捕获模式貌似 可以对空悬引用免疫,还让你认为你的闭包是独立的 避免使用默认捕获方式,而是清楚的写出你要捕获的变量以及捕获方式 C++14提供了在lambda式的形参声明中使用auto的能力 按值捕获可能导致空悬指针问题(尤其是this指针问题) 捕获只能针对在创建lambda表达式的作用域内可见的非静态局部变量(包括形参),因此我们无法捕获成员变量 对于捕获成员变量 的问题,我们可以将其复制到局部变量中,然后通过值捕获的方式进行捕获。或者我们可以使用C++14中的广义lambda捕获 使用默认值捕获似乎 表明闭包是自洽的,与闭包外的数据变化相绝缘。但这条结论不成立,原因在于lambda不仅以来局部变量和形参,他们还会依赖静态存储期对象。静态对象可以在lambda中使用,但是他们不能被捕获。从实际效果上看,lambda使用静态变量就好像是通过引用进行捕获 ,和按值默认捕获所暗示的含义有着直接的矛盾。
使用初始化捕获将对象移入闭包
C++11没有提供相应的做法,C++14可以使用初始化捕获完成 使用初始化捕获则我们有机会指定由lambda生成的闭包类中的成员变量的名字,并且我们可以使用表达式初始化该成员变量。 在C++11中经过手动实现类或者std::bind去模拟闭包初始化捕获
对auto&&类型的形参使用decltype以及std::forward
起因就是我们想要完美转发lambda的形参 做法如下:
auto f = [ ] ( auto && param)
{ return func ( normalize ( std:: forward < decltype ( param > ( param) ) ) ;
}
优先使用lambda,而非std::bind
lambda具有更高的可读性 lambda对于重载函数具有更好的适应性 使用lambda表达式可以拥有更高的执行效率(lambda可以内联,而bind中往往会使用的函数指针无法内联 ) 创建绑定对象时形参是以值传递的,调用绑定对象的形参是以引用传递,而lambda更加清晰表明了这些类型 在C++14中完全没有std::bind的应用场景,而在C++11中移动捕获(C++14默认支持)以及多态函数对象(C++14中支持auto形参)这两种情形下还要用 综上:lambda的可读性更好、表达力更强、可能运行效率也更高