lamda表达式

lamda表达式可以看作是一个匿名函数。编译器在编译的时候,会将lamda表达式处理成一个仿函数类,类名是类名是不重复的随机名称(因为一个作用域中可能存在多个仿函数),返回该仿函数的对象。

lamda既然可以看作是一个匿名函数,那就至少具备除函数名以外的两部分:返回值形参列表函数体

lamda表达式的书写格式

[capture-list](parameters)mutable->return-type{ statement }
/*
    [](const int x, const int y)mutable->int{
        return x + y;
    }
*/

目录

一、lamda表达式各部分说明 

1、capture-list(必要部分)

2、parameters(可选部分)

3、mutable(可选部分)

4、->return-type(可选部分)

5、 statement(必要部分)

二、lamda表达式的底层处理


一、lamda表达式各部分说明 

1、capture-list(必要部分)

(1) 捕获方式

capture-list表示捕获列表,lamda表达式可以通过捕获列表来获取上下文的变量,以供lamda表达式使用,无需通过形参列表传递变量。

捕获列表有两种方式来捕获变量:值传递、引用传递

捕获方式解释
[var]值传递的方式捕获变量 var,如[ a ],捕获上下文中的变量a
[=]值传递的方式捕获父作用域中的所有变量(包括this)
[&var]引用传递的方式捕获变量var
[&]引用传递的方式捕获父作用域中的所有变量(包括this)
[this]以值传递的方式捕获当前的this指针

(2) 注意事项

不能以相同的方式捕捉同一个变量。比如[=, a], = 表示以传值的方式捕捉所有的变量(包括变量a),a表示以传值的方式捕捉变量a,这个时候变量a以传值的方式被捕捉了两次

[=, a](){}        // 错误,重复捕获

不能捕捉父作用域之外的变量(包括全局变量)

int a = 10;
auto obj1 = []{};    // 注意,此时lamda表达式没有父作用域,捕获列表必须为空

int main()
{
    auto obj2 = [a]{};    // 错误,不可以捕获全局变量
}

 lamda表达式不能相互赋值。lamda表达式底层是被处理成一个类,不同的lamda表达式相当于不同的类(即便是类型相同也不行),不同的类之间不能相互赋值。

int main() {
	auto obj1 = [] {};
	auto obj2 = [] {};
	obj2 = obj1;        // 错误,obj1和obj2底层被处理成不同的类,他们的类名不可能重复
}

2、parameters(可选部分)

parameters表示调用lamda表达式时,要传递给lamda表达式的值。如果无需传递参数,该部分可以省略。

[]()->int{ return 0; };
// 或者
[]->int{ return 0; };

3、mutable(可选部分)

默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表parameters不可省略(即使参数为空)

[]()mutable->int{ return 0; };

4、->return-type(可选部分)

return-type表示lamda表达式的返回值类型。无返回值时,可以省略;有返回值时,也可以省略,此时交由编译器推导。

[](){ return 0; };

5、 statement(必要部分)

statement表示函数体,在函数体中,可以使用形参列表,也可以使用所有捕获到的变量,函数体中的语句可以有多条。

int main()
{
    int a = 10;
    auto obj = [&a](const int x){
        int c = x - a;
        return c;
    };
    return 0;
}

二、lamda表达式的底层处理

以下面这个lamda表达式为例

int main() {
	auto obj1 = [] {};   
	obj1();

    cout << typeid(obj1).name() << endl;
}

由此可见,lamda表达式实际上是被处理成一个类,类名是 lamda_<uuid> ,这样保证了每个lamda表达式的唯一性。lamda表达式的返回值就是该类的对象

我们通过反汇编来看一下lamda表达式的调用过程,我们会发现,类lamda_<uuid> 中重载了operator(),这样就可以使用对象来调用lamda表达式了。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值