C++11新特性——你所需要知道的关于匿名函数的一切

本文介绍了C++11引入的匿名函数(lambda表达式)特性,包括其基本语法、捕获列表的使用以及mutable关键字的作用。通过实例展示了如何定义和调用匿名函数,以及如何通过捕获列表访问外部变量。同时,详细解释了捕获列表的不同形式,如值捕获和引用捕获,并探讨了mutable关键字在匿名函数中如何允许修改捕获的变量。
摘要由CSDN通过智能技术生成

C++11新特性——你所需要知道的关于匿名函数的一切

概述

  • 在很多编程语言中,都存在着匿名函数,而C++也在11版本以后加入了这个新特性
  • 顾名思义,匿名函数就是不用写函数名的函数,这要就解决了起函数名这个烦人的问题啦(当你只使用一次时)
  • 接下来看看格式是怎样的
[捕获列表](参数列表)->返回类型{函数体}

//举个例子
[](int a,int b)->int{return a+b;}

//当然,你也可以给这个函数一个名字,就像声明一个变量一样,类型我们使用auto
auto f=[](int a,int b){return a+b;};	//注意这里要有分号

  • 我一开始并不理解,如果不给这个函数起名字的话,我该如何去调用它呢?
  • 这里给出两种办法,一种是立刻调用,但以后再也不能调用了;另一种就是把这个函数当成一个变量,给它起一个名字。
//立刻调用,但以后无法调用
int ans=[](int a,int b)->int{return a+b;}(10,54);

//给函数起名字
auto f=[](int a,int b){return a+b;};
f(10,90);
  • 细心的朋友会发现,我在上面那个例子中有一个没有指定函数返回值,这是可以的,可以由编译器自动推断出类型
  • 接下来,我们来说说mutable关键字和捕获列表

细说捕获列表

  • 一开始我并不理解,为啥要有一个这么奇怪的东西存在
  • 现在我大概了解了,是因为匿名函数往往都声明在一个函数内部,比如经常出现在main函数内部
  • 此时,这个函数在main函数的作用域内,但如果不传入参数,则main函数中的其余变量该匿名函数都是访问不到的
  • 其实我认为捕获列表就是一个参数列表,只不过在使用上可以更加方便,例如你要使用很多本地变量,你不需要一个个去传参
  • 下面举一个例子
int main()
{
    int t=10;
    auto f=[](){cout<<"t="<<t<<endl;};	//这是会报错的,因为访问不到变量t
    f();
    return 0;
}
  • 而假如你在参数列表中加入了这个变量,函数内部就可以访问到了,就像下面这样
int main()
{
    int t=10;
    auto f=[t](){cout<<"t="<<t<<endl;};
    f();
    return 0;
}
  • 接下来,我们来思考这个t的值在函数内部会不会改变呢?
  • 我们来做个实验
int main()
{
    int t=10;
    auto f=[t](){cout<<"t="<<t++<<endl;};	//这是会报错的,因为变量t无法被修改
    f();
    return 0;
}
  • 这样是会报错的,编译器会说表达式必须是一个可以修改的左值
  • 那你肯定就会想,如果想修改,可不可以传指针或者引用呢?
  • 答案是:可以滴!!
int main()
{
    int t=10;
    auto f=[&t](){cout<<"t+1="<<++t<<endl;};	//这是可以的,输出t+1=11
    f();
    cout<<"t="<<t<<endl;	//这里t已经被匿名函数修改了,所以输出11
    return 0;
}
  • 但是,目前不支持指针传递
  • 你现在也许会说,这和参数列表有啥区别,接下来,我们来看看这个捕获列表到底可以写点啥
捕获形式说明
[]不捕获任何外部变量
[变量名,…]默认以值的形式捕获制定的外部变量(逗号分割)
[this]以值的形式捕获this指针
[=]以值的形式捕获所有外部变量
[&]以引用的形式捕获所有外部变量
[&, a]以值的形式捕获外部变量a,以引用的形式捕获其他外部变量
[=, &a]以引用的形式捕获外部变量a,以值的形式捕获其他外部变量
  • 现在,你就该明白为啥要有捕获列表了

细说mutable关键字

  • 你肯定会问,哪来的mutable关键字?那是因为我还没有给出匿名函数的完整表达形式
[capture_list](params_list) mutable exception->return type {function_body} //这里的exception是异常的意思,这里我们不讨论
  • 学过c++面向对象的同学们应该知道,在一个类中,可以声明一个常函数,常函数不可以修改成员变量,除非这个成员变量使用了mutable关键字来修饰(我都快忘光了)
  • 同样的,匿名函数也是一个常函数,他默认是不可以修改捕获列表中变量的值的,除非在这个匿名函数参数列表后面加上mutable关键字
  • 这里,我们仅针对捕获列表为值传递的情况
  • 注意,mutable关键字可以省略,如果要写,则必须写()来代表参数列表,哪怕是无参函数
int main()
{
    int t=10;
    auto f=[t]() mutable {
        t+=10;	//这里,我们对t做了修改,所以mutable生效了
        cout<<"t="<<t<<endl;};
    f();	//输出20
    f();	//输出30
    cout<<"t="<<t<<endl;	//输出10,因为mutable只在函数内部改变
    
    return 0;
}
  • 我们可以看到,mutable生效了,我们可以修改t的值了
  • 且细心的人会发现,这并不影响匿名函数外面t的值
  • 且在函数内部,这个t的值就像被static关键字修饰了一样,这个变量的生命周期变得像main函数一样了
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值