lambda表达式-2

        当定义一个lambda时,编译器生成了一个与lambda对应的类类型,这个类类型是未命名的。因此,当向一个函数传递一个lambda时,同时定义了一个类类型以及该类型的一个对象:传递的参数就是该对象。类似的,使用auto定义一个用lambda初始化的变量时,实际上定义了一个lambda生成的类类型对象。

auto f = [] {return 42};

cout << f() << endl;  //打印42   

类似于参数传递,lambda变量的捕获方式也可以是值捕获引用捕获

值捕获

        与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝,因此,lambda创建后对值修改,不会影响到lambda内对应的值

int v1 = 42;

auto f = [v1] {return v1;};

v1 = 0;

cout << f() << endl; //输出42,f保存创建时的值

引用捕获

捕获变量时,可以采用引用捕获的方式

int v1 = 42;

auto f = [&v1] {return v1;};

v1 = 0;

cout << f() << endl; //输出0,采用引用捕获变量,而非拷贝

当以引用的方式捕获变量时,必须保证lambda执行时变量是存在的。


隐式捕获

除了显式列出捕获列表之外,还可以采用隐式捕获的方式,让编译器根据lambda体中的代码推断要使用那些变量,捕获变量的方式通过&或=来指定,&表示引用捕获,=表示值捕获。

auto wc = find_if(words.begin(), words.end(),

    [=] (const string &s)) {return s.size() >= sz;};

当一部分采用值捕获,另一部分采用引用捕获时,可以混合使用隐式捕获和显式捕获

for_each(words.begin(), words.end(),

    [&, c] (const string& s) {os << s << c};);   //os隐式捕获, c显式捕获

注意:混合使用隐式和显式捕获时,捕获列表的第一个元素必须时&或=,也就是说,隐式捕获必须放在前面。

          隐式捕获与显式捕获混合使用时,两种捕获的方式必须不同:

                即隐式捕获采用引用捕获,则显式捕获必须采用值捕获,反之亦然。


可变lambda

通过值捕获的变量在lambda体内默认不可修改,如果想要修改,需要加关键字mutable

int = 42;

auto f = [m] () mutable {return ++m};;

cout << f() << endl; //输出43

通过引用捕获的变量是否可以修改依赖于引用的类型是否为const


指定lambda返回类型

lambda体内是单一返回类型时,无需指定返回类型,编译器可以推算出来;

但是lambda体内包含return之外的任何语句时,都必须指定返回类型,否则编译器假定lambda返回void,有时会产生编译错误

例如,将负数替换为绝对值的算法和lambda:

transform(v1.begin(), v1.end(), v1.begin(), [] (int i) {return i < 0 ? -i : i; });  //正确,只有单一的return语句

transform(v1.begin(), v1.end(), v1.begin(), [] (int i) {if(i < 0) return -i; else return i; }); //错误,不能推断返回类型

这时,需要指定返回类型,使用尾置返回类型指定

transform(v1.begin(), v1.end(), v1.begin(),

        [] (int i) -> int {if(i < 0) return -i; else return i;});

注意:以上说明取自《C++ Primer(第5版)》,在VS2015中验证时发现,只要多条return语句返回的类型一致,就可以推断出返回类型,无须指定返回类型;

只有返回类型不一致时,才会产生编译错误:error C3487: “float”: 所有返回表达式必须推导为相同类型: 以前为“int”


Lambda表达式->,是Java 8中引入的一种函数式编程的特性。它可以简洁地表示一个匿名函数,可以作为参数传递给方法或函数。Lambda表达式的结构可以根据需要有零个或多个参数,参数可以明确声明或根据上下文推断。参数需包含在圆括号内,参数之间用逗号相隔。当只有一个参数且其类型可推导时,圆括号可以省略。Lambda表达式的主体可以包含零条或多条语句,如果主体只有一条语句,花括号{}可以省略。Lambda表达式的返回类型与主体表达式一致。如果主体包含一条以上的语句,表达式必须包含在花括号{}中形成代码块,返回类型与代码块的返回类型一致。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Lambda 表达式](https://blog.csdn.net/xxdw1992/article/details/103903210)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [深入浅出 Java 8 Lambda 表达式](https://blog.csdn.net/u012910595/article/details/70833510)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值