其实,最开始接触到lambda函数是在关于python匿名函数的教程中。后来在一些资料上也看到了关于C++中匿名函数的用法的相关讲解。那么,借着这次整理C++11新特征的机会,就对C++中的lambda函数进行一下归纳:

1. Lambda 函数与表达式

C++11 提供了对匿名函数的支持(即,没有函数名的函数),称为** Lambda 函数(也叫 Lambda 表达式)**。其作用主要在于,如果代码里面存在大量的小函数,而这些函数一般只被一两处调用,那么不妨将它们重构成Lambda表达式,也就是匿名函数。作用就是当你想用一个函数,但是又不想费神去命名一个函数。

Lambda 表达式本质上与函数声明非常类似,其通用表达形式——$[捕获区] (参数区)->返回类型 {代码区}:

  • [捕获区],指定在可见域范围内lambda表达式代码内可见的参数,即(除了形参之外)它可以使用的变量列表。在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为:
    • [],沒有定义任何变量,即不捕获外部的任何变量。使用未定义变量会引发错误。
    • [x, &y],x以传值方式传入(默认),y以引用方式传入。
    • [&],任何被使用到的外部变量都隐式地以引用方式加以引用。
    • [=],任何被使用到的外部变量都隐式地以传值方式加以引用。
    • [&, x],x显式地以传值方式加以引用。其余变量以引用方式加以引用。
    • [=, &z],z显式地以引用方式加以引用。其余变量以传值方式加以引用。
    • [this],以值的方式捕获 this 指针。
  • (参数区),指定lambda表达式内部变量定义
  • ->返回类型,是返回类型,如果 lambda 代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。如果没有 return 语句,则类似 void f(…) 函数。
  • {代码区},是Lambda表达式主题结构。

例如:

//通用表达形式:[捕获区](参数区)->返回类型 {代码区};
int n = [] (int x, int y) { return x + y; }(5, 4);      //n=9

P.s:Lambda函数通过“函数体”后面的‘()’传入参数,如上例中的(5,4)。

2. 使用场景

Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。就目前来看,Lambda函数最常用的使用场景在于:sort、for_each等自定义比较函数。

下面给出了一个非常具体且完整的Lambda表达式的使用样例,可帮助我们加深理解:

class CTest 
{ 
 public:  
   CTest() : m_nData(20) { NULL; }  
   void TestLambda()  
   {   
     vector<int> vctTemp;   
     vctTemp.push_back(1);   
     vctTemp.push_back(2);    

   // 无函数对象参数,输出:1 2   
   {    
     for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });   
   }   

   // 以值方式传递作用域内所有可见的局部变量(包括this),输出:11 12   
   {    
     int a = 10;    
     for_each(vctTemp.begin(), vctTemp.end(), [=](int v){ cout << v+a << endl; });   
   }    

   // 以引用方式传递作用域内所有可见的局部变量(包括this),输出:11 13 12   
   {    
     int a = 10;   
     for_each(vctTemp.begin(), vctTemp.end(), [&](int v)mutable{ cout << v+a << endl; a++; });    
     cout << a << endl;   
   }    

   // 以值方式传递局部变量a,输出:11 13 10   
   {    
     int a = 10;    
     for_each(vctTemp.begin(), vctTemp.end(), [a](int v)mutable{ cout << v+a << endl; a++; });    
     cout << a << endl;   
   }    

   // 以引用方式传递局部变量a,输出:11 13 12   
   {    
     int a = 10;    
     for_each(vctTemp.begin(), vctTemp.end(), [&a](int v){ cout << v+a << endl; a++; });    
     cout << a << endl;  
   }    

   // 传递this,输出:21 22 
   {  
     for_each(vctTemp.begin(), vctTemp.end(), [this](int v){ cout << v+m_nData << endl; });   
   }    

   // 除b按引用传递外,其他均按值传递,输出:11 12 17   
   {    
     int a = 10;    
     int b = 15;    
     for_each(vctTemp.begin(), vctTemp.end(), [=, &b](int v){ cout << v+a << endl; b++; });    
     cout << b << endl;   
   }     
   // 操作符重载函数参数按引用传递,输出:2 3   
   {    
     for_each(vctTemp.begin(), vctTemp.end(), [](int &v){ v++; });    
     for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });   
   }    
   // 空的Lambda表达式   
   {    
     [](){}();    []{}();   
   }  
 }  
 private:  int m_nData; 
};