前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lambda表达式

lambda表达式

作者头像
比特大冒险
发布2023-05-09 17:55:25
2220
发布2023-05-09 17:55:25
举报
文章被收录于专栏:小白历险记

前言:

        一般来说函数是承担着需求实现的重要内聚的组件,而函数内部的回调函数又达到解耦的作用,在对于后期的维护修改和他人的阅读都起到了积极的作用。        


1、lambda表达式的诞生

        在有时函数的本身的标准化让老油条的前辈们感到一丝丝的麻烦,例如算法库(algorithm)中的sort()函数,

 为了同时实现排序的升序和降序(不传入comp,默认为升序),我们会传入比较函数对象

例如下面的 myfunction ()与 仿函数myclass

代码语言:javascript
复制
#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector

bool myfunction (int i,int j) { return (i<j); }

struct myclass {
  bool operator() (int i,int j) { return (i<j);}
} myobject;

int main () {
  int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

  // using object as comp
  std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

这就让人让人无语了,就为了一个大于和小于,还额外写函数。。。。。

2、lambda表达式语法

lambda表达式书写格式:

[capture-list] (parameters) mutable -> return-type { statement}

2.1、lambda表达式各部分说明

  • [capture-list] : 捕捉列表:该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
  • (parameters):参数列表:与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
  • mutable:默认情况下:lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  • ->returntype:返回值类型:用追踪返回类型形式声明函数的返回值类型,没有返回 值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推 导。
  • {statement}:函数体:在该函数体内,除了可以使用其参数外,还可以使用所有捕获 到的变量。

注意:         在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为 空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

 例子:

代码语言:javascript
复制
int main()
{
    // 最简单的lambda表达式, 该lambda表达式没有任何意义
    []{};
    // 省略参数列表和返回值类型,返回值类型由编译器推导为int
    int a = 3, b = 4;
    [=]{return a + 3; };
    // 省略了返回值类型,无返回值类型
    auto fun1 = [&](int c){b = a + c; };
    fun1(10)
    cout<<a<<" "<<b<<endl;
    // 各部分都很完善的lambda函数
    auto fun2 = [=, &b](int c)->int{return b += a+ c; };
    cout<<fun2(10)<<endl;
    // 复制捕捉x
    int x = 10;
    auto add_x = [x](int a) mutable { x *= 2; return a + x; };
    cout << add_x(10) << endl;
    return 0;
}

通过上述例子可以看出,lambda表达式实际上可以理解为无名函数,该函数无法直接调 用,如果想要直接调用,可借助auto将其赋值给一个变量。

2.2、捕获列表说明

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

  • [var]:表示值传递方式捕捉变量var
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
  • [&var]:表示引用传递捕捉变量var
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
  • [this]:表示值传递方式捕捉当前的this指针

注意: a. 父作用域指包含lambda函数的语句块 b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。

比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量            [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量

c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复

d. 在块作用域以外的lambda函数捕捉列表必须为空。 e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者 非局部变量都会导致编译报错

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:
  • 1、lambda表达式的诞生
  • 2、lambda表达式语法
    • 2.1、lambda表达式各部分说明
      • 2.2、捕获列表说明
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档