Bootstrap

C++中的lambda表达式

1.引入背景

        在c/c++中,函数有类型,但不存在对应该类型的变量,只能用指针间接操作。函数是全局的,没有作用域和生存周期的概念(static,namespace只是限定了范围,避免命名冲突)。此外,函数中不能定义函数,即不能嵌套定义。

        变量和函数是程序最重要的两个部分。变量有类型,有值,有作用域。而函数有类型,没有值,没有作用域。因此,两者不能一致的处理。

        c++11引入lambdas表达式,它是一个变量,可以随时定义函数,有作用域和生命周期,实现了函数的局部化。

2.lambda的形式

          C++ 没有为 lambda 表达式引入新的关键字,只是用 [ ]作为表达式的引出符, 后面像普通函数一样,()中声明函数参数,{}中定义函数体。

auto f1 = [](){};   

         lambda 表达式可以嵌套定义。

auto f1 = []()                
{
    auto f2 = [](int x)         // 嵌套定义lambda表达式
    {
        return x*x;
    };
  
};  

        下面是一个直接调用lambda表达式的示例:

#include <iostream>
int main()
{
  []{
     std::cout <<"hello lambda" <<std::endl; 
  }();
  return 0;
}

    运行结果

hello lambda

    实际上,我们很少在定义时直接调用,而是采用如下方式:

#include <iostream>
int main()
{
  auto f = []{
     std::cout <<"hello lambda" <<std::endl; 
  };
  
  f();
  return 0;
}

     运行结果同上。

2.变量捕获

        “[=]”表示按值捕获所有外部变量,表达式内部是值的拷贝,并且不能修改;

        “[&]”是按引用捕获所有外部变量,内部以引用的方式使用,可以修改;

          []”里明确写出外部变量名,指定按值或者按引用捕获,

2.1捕获值

         下面的例子中,变量id以的方式进入lambda表达式。执行f()时,虽然id已经自增,但是 lambdas捕获id时,id的值是0,因此输出0;main中输出id是自增后的值。

#include <iostream>
int main()
{
  int id = 0;
  auto f = [id](){
      std::cout <<"id = " << id <<std::endl;     
  };
  
  id++;
  f();
  std::cout <<"id = " << id <<std::endl;    
  return 0;
}

   运行结果

id = 0
id = 1
2.2捕获引用

          变量id以引用的方式进入lambda表达式

#include <iostream>
int main()
{
  int id = 0;
  auto f = [&id](){
      id = id+10;
      std::cout <<"id = " << id <<std::endl;     
  };
  
  id++;
  f();
  std::cout <<"id = " << id <<std::endl;    
  return 0;
}

   运行结果

id = 11
id = 11

3.泛型的 lambda

        在 C++14 里,lambda 表达式可以实现“泛型化”,相当于简化了的模板函数。下面的例子中,整型,浮点型,字符串都可以传给lambda表达式。

#include <iostream>
#include <string>
int main()
{
    auto f = [](const auto& x)        // 参数使用auto声明,泛型化
    {
        return x + x;
    };
    
    std::string str = "matrix";
    std::cout <<"f(3) = " << f(3) << std::endl;             // 参数类型是int
    std::cout <<"f(0.8) = "<< f(0.8) << std::endl;         // 参数类型是double
    std::cout << "f(str) = " << f(str) << std::endl;          // 参数类型是string  
    return 0;
}

 运行结果

f(3) = 6
f(0.8) = 1.6
f(str) = matrixmatrix

;