C/C++面试试题专栏:c++ lambda表达式(四)

lambda表达式的完整声明如下:

[capture list](params list) mutable exception->return type{function body}

//capture list:捕获列表

/* [var]:以值的形式捕获
   [&]:引用方式捕获
   [=]:值捕获

//params list:参数列表
//mutable: 捕获列表可以修改
//exception:异常处理
//return type:返回值类型

看一道简单的例子:

#include<iostream>
using namespace std;

int main()
{
    int a=9;
    auto fun1=[=]()mutable{return ++a;};
    cout<<fun1()<<endl;
    cout<<a<<endl;
    return 0;
}

输出的结果为:

以值传递,在lambda表达式中,修改a的值后,main()中a的值并未改变。说明传进去的a是一个副本。这也普通函数的参数传递中的值传递是一样。但是,普通函数按值传递,可以对得到的形参进行任意改变,如:++param,--param等,lambda表达式可以任意改变按值传递的参数的值吗?请看下面两道列子:

看一道难一点的列子:

#include<iostream>
using namespace std;

int main()
{
    int a=9;
    auto fun1=[=]{return a+1;};
    auto fun2=[&]{return a+1;};
    cout<<"fun1:"<<fun1()<<endl;
    cout<<"fun2:"<<fun2()<<endl;
    ++a;
    cout<<"++a执行之后的值"<<endl;
    cout<<"fun1:"<<fun1()<<endl;
    cout<<"fun2:"<<fun2()<<endl;

    return 0;
}

程序运行之后结果如下:

为什么++a执行之后,fun1的值不是11呢?

lambda表达式中,a被视为常量。初始化一次后,保持不变。相反的,如果需要捕捉的值成为Lambda函数运行时的变量,则应该采用按引用方式进行捕捉。 

再看一道例子:

#include<iostream>
using namespace std;

int main()
{
    int a=9;
    auto fun1=[=]{return ++a;};//代码片段1
    auto fun2=[&]{return ++a;};//代码片段2
    auto fun2=[=]()mutable{return ++a;};//代码片段3
    return 0;
}

若运行程序,会有什么问题?

代码片段1:编译报错,error: increment of read-only variable ‘a’

代码片段2:正确运行

代码片段3:正确运行

默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。按照规定,一个const的成员函数是不能在函数体内修改非静态成员变量的值。

总结:

1.若按值传递,表达式内部复制了一份捕获的变量;不论被捕获的变量如何改变(如++a),其已被捕获的值,在表达式内部保持不变;

2.若按引用传递,表达式内部的值,使用的就是被捕捉的变量的值;所以,被捕获的变量改变时,其内部的值也会改变;

3.按值传递,若想修改变量的值,则需要加mutable关键字;因为lambda默认是常函数;在一个常函数内部,只能修改static类型变量的值,不能修改非static类型变量的值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值