- C++11特性之一
lambda表达式有如下优点:
- 声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序,好的可读性和可维护性。
- 简洁:不需要额外再写一个函数或者函数对象,避免了代码膨胀和功能分散,让开发者更加集中精力在手边的问题,同时也获取了更高的生产率。
- 在需要的时间和地点实现功能闭包,使程序更灵活。
lambda表达式用法:
// lambda 表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。 [ capture ] ( params ) opt -> ret { body; }; // capture 是捕获列表,params 是参数表,opt 是函数选项,ret 是返回值类型,body是函数体。
lambda表达式示例:
使用 lambda 表达式捕获列表auto f = [](int *a*) -> int { return *a* + 1; }; cout << f(1) << endl; // 输出2
C++11 中允许省略 lambda 表达式的返回值定义。
auto f = [](int *a*) { return *a* + 1; }; // 编译器就会根据 return 语句自动推导出返回值类型 cout << f(1) << endl; // 输出2
- 初始化列表不能用于返回值的自动推导,需要显式给出具体的返回值类型。
- lambda 表达式在没有参数列表时,参数列表是可以省略的。
lambda 表达式还可以通过捕获列表捕获一定范围内的变量:
- [] 不捕获任何变量。
- [&] 捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
- [=] 捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。
- [=,&foo] 按值捕获外部作用域中所有变量,并按引用捕获 foo 变量。
- [bar] 按值捕获 bar 变量,同时不捕获其他变量。
- [this] 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。
lambda表达式易错点:
lambda 表达式的类型int a = 0; auto f = [=](){return a;}; a += 1; cout << f() << endl; // 输出0 // lambda 表达式按值捕获了所有外部变量。在捕获的一瞬间,a 的值就已经被复制到f中了。 // 之后 a 被修改,但此时 f 中存储的 a 仍然还是捕获时的值,因此,最终输出结果是 0。 // 如果希望 lambda 表达式在调用时能够即时访问外部变量,我们应当使用引用方式捕获。
如果希望去修改按值捕获的外部变量应当怎么办呢?这时,需要显式指明 lambda 表达式为 mutable:
int a = 0; auto f1 = [=]{ return a++; }; // error,修改按值捕获的外部变量 auto f2 = [=]() mutable { return a++; }; // OK,mutable // 被 mutable 修饰的 lambda 表达式就算没有参数也要写明参数列表
“闭包类型(Closure Type)”。它是一个特殊的,匿名的非 nunion 的类类型。
对于没有捕获任何变量的 lambda 表达式,还可以被转换成一个普通的函数指针。
声明式的编程风格,简洁的代码lambda 表达式可以说是就地定义仿函数闭包的“语法糖”。它的捕获列表捕获住的任何外部变量,最终均会变为闭包类型的成员变量。而一个使用了成员变量的类的 operator(),如果能直接被转换为普通的函数指针,那么 lambda 表达式本身的 this 指针就丢失掉了。而没有捕获任何外部变量的 lambda 表达式则不存在这个问题。
这里也可以很自然地解释为何按值捕获无法修改捕获的外部变量。因为按照 C++ 标准,lambda 表达式的 operator() 默认是 const 的。一个 const 成员函数是无法修改成员变量的值的。而 mutable 的作用,就在于取消 operator() 的 const。
需要注意的是,没有捕获变量的 lambda 表达式可以直接转换为函数指针,而捕获变量的 lambda 表达式则不能转换为函数指针。
lambda 表达式的价值在于,就地封装短小的功能闭包,可以极其方便地表达出我们希望执行的具体 *** 作,并让上下文结合得更加紧密。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)