不那么新的C++标准学习笔记 logo 不那么新的C++标准学习笔记

编译器支持最低版本要求:

  • GCC: 4.5(v1.1)
  • MSVC: 16.0
  • Clang: 3.1

提案: v0.9 - N2550/v1.0 - N2658/v1.1 - N2927

Lambda表达式就是匿名函数,在C++11之前Boost凭借C++语言强大的template和预处理宏,以及库作者强悍的奇技淫巧实现了Boost.lambda和更高级用法Boost.phoenix,但没有语言层面的支持,完全用库实现不但稍显累赘,而且代码观感不佳。C++11在语言层面实现了lambda,语法定义如下:

[capture](parameters)mutable -> return-value { statement }

所以一个最简单的lambda表达式是这样的:

[]{}

尽管它什么事都没干,也没什么作用,但确实是一个合法的lambda表达式。

捕捉列表可以有0个,或1个,或多个捕捉项,以逗号分隔,可以有以下几种形式:

  1. [var],表示值传递方式捕捉变量var
  2. [&var],表示引用传递方式捕捉变量var
  3. [=],表示值传递方式捕捉所有父作用域的变量。
  4. [&],表示引用传递方式捕捉所有父作用域的变量。
  5. [this],表示捕捉当前this指针,但不能捕捉*this,但在C++17中已经可以捕捉this也包括在[=][&]中。

然后可以多个捕捉项组合:

[=, &a, &b]
[&, a, b]

但是多个捕捉项不能重复:

[a, a]
[=, a]
[&, &a]

捕捉列表的不同,效果也会不同:

Lambda表达式在功能上跟仿函数(functor,也称函数对象,function object)非常相似:可以保存外部变量的状态,可以传入参数,可以被调用。编译器在实现lambda表达式时也采用了与仿函数相似的方法。

每个lambda表达式都有自己特有的类型,也就是说不能仅仅因为捕捉列表、参数列表、返回值类型相同而把一个lambda表达式赋给另一个保存着lambda表达式的变量,却可以把一个保存了lambda表达式的变量赋给另一个变量:

auto f = [](int n)->int { return n;};
decltype(f) f2 = f; // 正确
decltype(f) f3 = [](int n)->int { return n;};  // 编译错误

Lambda表达式在C++中最典型的应用场景是作为被回调体,比如STL诸多算法需要提供谓词(predicate),简短的lambda比函数指针和仿函数都要更适合承担这份工作:

但是lambda表达式并不能完全取代仿函数:

相关链接

感觉不错,小额赞助一下!

Hosted by Coding Pages, 本站由 @missdeer 创建,由 Jekyll 于 2018-06-17 生成,感谢 CloudCannon 制作的theme: Edition ,感谢 Let's Encrypt 提供免费的SSL证书服务。本站点采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。© 2018