匿名函数lambda

本文详细介绍了C++中的lambda表达式,包括基本语法、捕获列表(值捕获、引用捕获、表达式捕获和泛型)、可变性和mutable修饰的使用。重点讲解了如何在lambda中处理外部变量以及C++14后的新特性。
摘要由CSDN通过智能技术生成

一、匿名函数的基本语法

  • lambda 表达式可以看成是一般函数的函数名被略去,返回值使用了一个 -> 的形式表示。
  • 唯一与普通函数不同的是增加了捕获列表
[捕获列表](参数列表) -> 返回类型{
	函数体
}
auto Add = [](int a, int b) -> int {
	return a + b;
};
cout << Add(1, 2) << endl;
  • 一般情况下,编译器可以自动推断出 lambda 表达式的返回值类型,所以我们可以不指定返回值类型。
  • 但是如果函数体内有多个 return 语句时,编译器无法自动推断出返回值类型,此时必须指定返回值类型。
auto Add = [](int a, int b) {
	return a + b;
};
cout << Add(1, 2) << endl;

二、捕获列表

  • 有时候,需要在匿名函数内使用外部变量,所以用捕获列表来传递参数。
  • 根据传递参数的行为,捕获列表可分为以下几种:
  • 值捕获。
    • 与参数传值类似,值捕获的前提是变量可以拷贝,不同之处则在于:被捕获的变量在 lambda 表达式被创建时拷贝,而非调用时才拷贝。
      int c = 30;
      int d = 40;
      auto Add = [c, d](int a, int b) -> int {
      	cout << "d = " << d << endl;
      	return c;
      };
      
      d = 20;
      
      cout << Add(1, 2) << endl;
      // d = 40
      // 30
      
  • 引用捕获。
    • 与引用传参类似,引用捕获保存的是引用,值会发生变化。
      int c = 30;
      int d = 40;
      auto Add = [&c, &d](int a, int b) -> int {
      	c = a;
      	cout << "d = " << d << endl;
      	return c;
      };
      
      d = 20;
      
      cout << Add(1, 2) << endl;
      // d = 20
      // 1
      
  • 隐式捕获和空捕获。
    • 手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时候可以在捕获列表中写一个 &= 向编译器声明采用引用捕获或者值捕获
      int c = 30;
      int d = 40;
      // [] 空捕获,不能使用外部的变量
      // [=] 传值,lambda 外部的变量都能使用
      // [&] 传引用值,lambda 外部的变量都能使用
      auto Add = [&](int a, int b) -> int {
          c = a;
          cout << "d = " << d << endl;
          return c;
      };
      
      d = 20;
      
      cout << Add(1, 2) << endl;
      // d = 20
      // 1
      
  • 表达式捕获。
    • 上面提到的值捕获、引用捕获都是已经在外层作用域声明的变量,因此这些捕获方式捕获的均为左值,而不能捕获右值。
    • C++14 之后支持捕获右值,允许捕获的成员用任意的表达式进行初始化,被声明的捕获变量类型会根据表达式进行判断,判断方式与使用 auto 本质上是相同的。
      auto important = std::make_unique<int>(1);
      
      auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
          return x + y + v1 + (*v2);
      };
      
      cout << add(3,4) << endl; // 9
      
  • 泛型 lambda。
    • 在 C++14 之前,lambda 表示的形参只能指定具体的类型,没法泛型化。
    • 从 C++14 开始, lambda 函数的形式参数可以使用 auto 关键字来产生意义上的泛型。
      auto add = [](auto x, auto y) {
              return x + y;
          };
      
      cout << add(1, 2) << endl;     // 3
      cout << add(1.1, 1.2) << endl; // 2.3
      
  • 可变 lambda。
    • 采用值捕获的方式,lambda 不能修改其值,如果想要修改,使用 mutable 修饰。
      int v = 5;
      // 值捕获方式,使用 mutable 修饰,可以改变捕获的变量值
      auto ff = [v]() mutable {
      	return ++v;
      };
      
      v = 0;
      
      auto res = ff(); 
      cout << res << endl; // 6
      
    • 采用引用捕获的方式,lambda 可以直接修改其值。
      int v = 5;
      // 引用捕获方式,可以直接修改变量值
      auto ff = [&v] {
      	return ++v;
      };
      
      v = 0;
      
      auto res = ff(); 
      cout << res << endl; // 1
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值