之前刷题的时候,一直会看见自定义sort的做法,一般的形式是,重新写一个bool的函数,然后作为参数传递给sort函数,但有时候,也会看见,直接传进去一个lambda表达式,比如以下的形式

sort(myStr.begin(),myStr.end(),
            [](string &a,string &b){
   
                return (a+b)>(b+a);
            });

sort的第三个参数是一个谓词(predicate),也就是一个可调用的表达式。但是算法一般接受一元谓词或者二元谓词,如果需要传递更多的参数,就可以使用lambda表达式

lambda表达式的一般形式

[捕获列表] (参数列表) -> 返回类型 {函数体}

lambda 表达式的一般形式:
    [capture list] (parameter list) ->retur  type {
   function body} 

捕获列表

捕获列表就是在lambda函数体里面用到的局部变量,比如想用使用find_if找到数组里面的第一个大于value的值:

    int value=3
    auto ans = find_if(vi.begin(), vi.end(),
                       [value] (int &a){
   
                           return a>=value;
                       });

对于捕获列表,可以采用两种方式传递:

  1. 值捕获
      就是直接传递值,被捕获的值在lambda创建的时候进行拷贝,也就是说,在lambda后面修改该值,不会影响lambda;
  2. 引用捕获
      就是直接传引用,因此,在lambda后面修改该值,会影响lambda;
    int v1 = 42;
    int v2=42;
    auto f1 = [v1]() {
    return ++v1; };
    auto f2 = [&v1]() {
    return ++v1; }; 
    v1 = 0; 
    v2 = 0;
    auto j1 = f1(); //42 被捕获变量的值在lambda创建时拷贝
    auto j2 = f2(); //0 //为什么,因为捕获列表传进去的是一个引用,在这一行改变了引用对象的值

参数列表

参数列表就是上面小括号里面传进去的实参

返回类型

一般的,在函数体内内部,如果除了单一的return语句,还有其他的语句,编译器就会假定返回类型为void。比如你想使用transform将数组里面的元素转变为绝对值,这个时候,就需要指定返回类型为int;当然,对于比较简单的if else,你也可以使用正则表达式代替,不指定返回类型

    transform(vi.begin(), vi.end(), vi.begin(),
              [](int i) -> int {
   
                  if (i < 0)
                      return -i;
                  else
                      return i;
              });
//不指定返回类型的版本 
transform(vi.begin(), vi.end(), vi.begin(),
              [](int i) {
   return i<0? -i:i ;});
              });

函数体

也就是lambda表达式大括号里面的内容