【C++11】lambda表达式

文章目录

  • 1. 为什么要有lambda表达式存在?
  • 2. lambda表达式的基本语法
    • 基本使用
    • 捕捉列表和异变的使用
      • 传值捕捉
        • 异变的使用
      • 引用捕捉
      • 混合捕捉
  • 3. 线程与lambda表达式之间的关系
    • 线程与lambda的结合使用
    • 将m个线程打印n次
  • 4. lambda原理
    • 一个 lambda对象有多大?
    • 转化为汇编探究

1. 为什么要有lambda表达式存在?

【C++11】lambda表达式_第1张图片

以商品举例,可以通过名字 排序,可以通过价格排序,可以通过评价排序

在C++中,使用仿函数可以进行 价格的比较
若不看仿函数具体实现,则无法通过仿函数对象 来知道 该仿函数到底是怎么比较的
所以就提出了lambda表达式

2. lambda表达式的基本语法

1.[capture-list] :捕捉列表
该列表出现在lambda的开始位置
捕捉列表可以捕捉上下文变量供 lambda函数使用
不可省略,若不进行任何捕捉,则写成 []


2.(paraments) :参数列表
与函数的参数列表相同
若没有参数,可以将()省略


3.mutable:异变

(后面会详细说)


4.-> return- type :返回值类型

可省略,编译器会对返回类型进行推导


5.{statement} :函数体

在函数体内部,除了使用其参数外,还可用捕捉的变量

基本使用

捕捉列表:不可省略,若不进行任何捕捉,则写成 []
参数列表:存在两个参数 x 和 y
异变:不使用时,可省略
返回值类型:是可以省略的,编译器会自动推导 (但一般不建议省略)
函数体:要注意内部是要有分号的,代表语句结束

表达式整体代表一个lambda对象,是可以被调用的


【C++11】lambda表达式_第2张图片

将返回值类型省略,编译器可以自动推导


【C++11】lambda表达式_第3张图片

通过lambda表达式 即可清楚了解 lambda表达式对象内部如何实现比较的

若想修改升序或降序,只需修改对应的lambda表达式代码即可

捕捉列表和异变的使用

若不进行任何捕捉,使用lambda表达式完成交换

【C++11】lambda表达式_第4张图片

传值捕捉

若想用外面域的变量,则需要捕捉, 捕捉多个值,用逗号分割 【C++11】lambda表达式_第5张图片

由于是传值捕捉,所以捕捉过来的a和b是外面的拷贝,是无法改变的

异变的使用

【C++11】lambda表达式_第6张图片

加入mutable 异变,即可修改传值捕捉所过来的a和b
但是无法完成交换,传值捕捉所进行的修改,并不会影响 本身

引用捕捉

【C++11】lambda表达式_第7张图片

使用引用的方式,即可通过修改捕捉后的a和b,来影响本身 的值进行修改

混合捕捉

【C++11】lambda表达式_第8张图片

a引用捕捉,b传值捕捉


【C++11】lambda表达式_第9张图片

假设有一堆的变量,不想一个一个捕捉
使用 [&] 即全部使用引用捕捉


【C++11】lambda表达式_第10张图片

使用 [=] 即全部使用传值捕捉


【C++11】lambda表达式_第11张图片

除了a使用传值捕捉以外,其他全部使用引用捕捉

3. 线程与lambda表达式之间的关系

pthread库是 POSIX线程库,POISIX(可移植操作系统接口)
windows 与linux 下的库是不一样的

C++11中,linux和windows下都支持多线程程序 即 使用 thread库


【C++11】lambda表达式_第12张图片

第一个参数 作为模板类型,所以可以是 函数指针 、仿函数对象 或 lambda对象 为可调用的对象即可

对于第二个参数 Args&&…args来说
通过模板的可变参数,想传几个参数都可以
使用万能引用,当为左值时,发生引用折叠,即可以看作是& ,调用深拷贝
当为右值时,发生移动构造,进行资源转移


【C++11】lambda表达式_第13张图片

对于thread库的调用,与linux中的pthread库大部分功能都是类似的,
如:join 与 pthread_jojn 功能相同 ,线程等待 若一个新线程被创建出来,需要主线程就等待的
detach 与pthread_detach 功能相同,线程分离 默认是阻塞的 ,即主线程等待 新线程退出,主线程 想做其他事情

线程与lambda的结合使用

【C++11】lambda表达式_第14张图片

使用lambda对象 作为可被调用对象
通过lambda表达式对象,
先将 a进行传值捕捉,将1作为sum ,再进行循环
再将 b进行传值捕捉,将2作为sum,再进行循环


将m个线程打印n次

允许移动赋值


【C++11】lambda表达式_第15张图片

每次都创建一个线程,其整体可以看作是一个匿名对象,属于右值,所以进行移动赋值
将新建线程的资源转移到线程数组中

4. lambda原理

一个 lambda对象有多大?

【C++11】lambda表达式_第16张图片

实际上是1字节


转化为汇编探究

编译器会把lambda处理成仿函数

【C++11】lambda表达式_第17张图片

先查看仿函数的汇编

【C++11】lambda表达式_第18张图片 【C++11】lambda表达式_第19张图片

先调用构造函数,使r1成为仿函数对象
再调用rate类中的operator()


再查看lambda的汇编

【C++11】lambda表达式_第20张图片

由编译器生成一个不重复的类,(保证每个lambda都不一样),用该类调用构造函数
以及 调用类中的 operator()

仿函数汇编的调用与lambda汇编的调用都是先调用构造函数,在调用operator(),说明lambda底层就为仿函数实现的


根据仿函数,生成仿函数的类,由于仿函数的类是空类 ,所以为1字节 即lambda对象为1字节

你可能感兴趣的:(c++,开发语言)