C++11 Lambda表达式

本文详细介绍了C++中的Lambda函数,包括其基本语法、参数捕获方式及其实例应用。Lambda函数允许匿名定义和直接使用,可以方便地进行函数对象的创建。通过[=]和[&]捕获方式,Lambda可以访问并操作外部变量。示例展示了值传递和引用传递的区别,以及如何影响函数体内部对变量的修改。Lambda表达式的使用提高了代码的灵活性和可读性。
摘要由CSDN通过智能技术生成

1、Lambda基本知识点

Lambda函数又称匿名函数,匿名函数就是没有名字的函数

[] { //Lambda表达式以[]标识开始
  do_something1();
  do_something2();
}(); //表达式结束,可以直接调用

当然我们也可以给表达式传递参数,可以参考下面的Lambda函数, 其使用起来就像是一个普通函数。 例如, 下面代码是将vector中的元素使用 std::cout 进行打
印:

std::vector<int> data=make_data();
std::for_each(data.begin(),data.end(),[](int i){std::cout<<i<<"\n";});

当Lambda函数体中有多个return语句, 就需要显式的指定返回类型。 只有一个返回语句的时候, 也可以这样做, 不过这样可能会让你的Lambda函数体看起来更复杂。 返回类型可以使用跟在参数列表后面的箭头(->)进行设置。 如果Lambda函数没有任何参数, 还需要包含(空)的参数列表, 这样做是为了能显式的对返回类型进行指定。 对条件变量的,预测可以写成下面这种方式:

cond.wait(lk,[]()->bool{return data_ready;});

对Lambda函数进行扩展, 比如: 加上log信息的打印, 或做更加复杂的操作和获取返回值:

cond.wait(lk,[]()->bool{
  if (data_ready) {
    return true;
  } else {
    return false;
  }
});

Lambda基本知识点:

1、[函数对象参数],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。函数对象参数有以下形式:
(1) 空 没有使用任何函数对象参数。
(2) = 函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
(3) & 函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
(4) this 函数体内可以使用Lambda所在类中的成员变量。
(5) a 将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
(6) &a。将a按引用进行传递。
(7) a, &b。将a按值进行传递,b按引用进行传递。
(8) =,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。
(9) &, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。
Lambda函数使用空的 [] (Lambda introducer)就不能引用当前范围内的本地变量; 其只能使用全局变量, 或将其他值以参数的形式进行传递。 当想要访问一个本地变量, 需要对其进行捕获。 最简单的方式就是将范围内的所有本地变量都进行捕获, 使用 [=] 就可以完成这样的功能。 函数被创建的时候, 就能对本地变量的副本进行访问了。
2、(操作符重载函数参数),标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(如:(a,b))和按引用(如:(&a,&b))两种方式进行传递。
3、mutable或exception声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。exception声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用throw(int)。
4、->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。
5、{函数体},标识函数的实现,这部分不能省略,但函数体可以为空。

2、Lambda捕获本地变量方式【=】 和【&】

从上面可知,【=】是将参数进行值传递,【&】是将参数进行引用传递的。

在 c++[]为lambda的捕获区,用于捕获外部变量,我们可以看一看。
int a = 5;
auto lambda = [=](int value) { std::cout << "value: " << a << value << std::endl; };
= 表示传值
& 表示传入引用
[&a] 表示传入 a 变量的引用,而[a]表示传入值。

具体区别如下:
【=】和【&】示例如下:

/*************************************************************************
      > File Name: lambda.cpp
      > Author: 小和尚念经敲木鱼
      > Mail:  
      > Created Time: Sun 17 Oct 2021 10:08:13 PM CST
 ***********************************************************************/

#include <iostream>
#include <functional>

using namespace std;
/************************************************************************
* 文件说明
* lambda
************************************************************************/
std::function<int(int)> make_offset(int offset)
{
  return [=](int j){return offset+j;};
}

int main(int agc,char * agv[])
{
  int a = 10, b = 120;
  std::function<int(int)> offset_test1 = make_offset(20);
  std::function<int(int)> offset_test2 = make_offset(120);

  std::cout<<offset_test1(30)<<","<<offset_test2(30)<<std::endl;
  std::cout<<offset_test1(30)<<","<<offset_test2(30)<<std::endl;
  
  int base_value = 20;

  std::function<int(int)> offset_1 = [=](int j) {
    //base_value = base_value + j;
    return base_value + j;
  };
  std::cout << "base_value = " << base_value << std::endl;
  std::cout << "value = " << offset_1(12) << std::endl;
  std::cout << "offset_1 base_value = " << base_value << std::endl;

  std::function<int(int)> offset_2 = [&](int j) {
    base_value = base_value + j;
    return base_value + j;
  };
  std::cout << "base_value = " << base_value << std::endl;
  std::cout << "value = " << offset_2(12) << std::endl;
  std::cout << "offset_2 base_value = " << base_value << std::endl;

  return 0;
}
//OUT
//50,150
//50,150
//base_value = 20
//value = 32
//offset_1 base_value = 20 未修改base_value 
//base_value = 20
//value = 44
//offset_2 base_value = 32 修改了base_value 
/******************************end of file******************************/

3、总结

Lambda表达式使用起来非常方便,但是读起来有点难懂,具体是值传入还是引用传入需要注意。
补充其他具体细节。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给大佬递杯卡布奇诺

你们的鼓励就是我传作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值