1. 程式人生 > >C++11 lambda

C++11 lambda

捕獲欄位:空,=,&

空:不能訪問外部變數

=:按值訪問外部變數,[var]按值訪問var,[=]按值訪問所有變數

&:引用方式訪問外部變數,[&var]引用訪問var變數,[&]引用訪問所有變數

組合[=,&var]能夠按照引用訪問var和按值訪問所有變數

特殊情況:lambda函式在某個成員函式裡面時,[this]和[=]可以訪問這個成員函式所能訪問的物件   

理解捕獲的概念:

// declaring_lambda_expressions2.cpp  
// compile with: /EHsc /W4  
#include <functional>  
#include <iostream>  
  
int main()  
{  
   using namespace std;  
  
   int i = 3;  
   int j = 5;  
  
   // The following lambda expression captures i by value and  
   // j by reference.  
   function<int (void)> f = [i, &j] { return i + j; };//宣告定義f的時候,使用i的值傳入,j的引用  
  
   // Change the values of i and j.  
   i = 22;  
   j = 44;  
  
   // Call f and print its result.  
   cout << f() << endl; //output:3+44=47  
}  

1、獲取變數型別

  1. #include <typeinfo.h>
  2. int a = 1;  
  3. typeid(a).name();  

2、lambda表示式用法

C++11 提供了對匿名函式的支援,稱為 Lambda 函式(也叫 Lambda 表示式)。Lambda 表示式把函式看作物件。Lambda 表示式可以像物件一樣使用,比如可以將它們賦給變數和作為引數傳遞,還可以像函式一樣對其求值。Lambda 表示式本質上與函式宣告非常類似。
  1. [capture](parameters)->return-type{body}  
  2. //例如
  3. [](int x, int y) -> int { int z = x + y; 
    return z + x; }  
  4. int main(){  
  5.   int a = 1;  
  6.   int b = 2;  
  7.   auto lambda = []{return a + b;};   
  8.   //error! 空捕獲列表,無法使用作用域內其他變數
  9.   auto lambda = [](int a, int b){return a + b;};   
  10.   //success
  11.   auto lambda = [=]{return a + b;};   
  12.   //success, 值傳遞
  13.   auto lambda = [=]{a++; b++; return a + b;};   
  14.   //error! 值傳遞無法修改變數值
  15.   auto lambda = [&]{a++; b++; return a + b;};   
  16.   //success, 引用傳遞
  17.   auto lambda = [&a, b]{a++; b++; return a + b;};   
  18.   //error, 變數a引用傳遞,變數b值傳遞,故b不可修改
  19. }  

3、將lambda表示式作為函式引數傳遞

想要使lambda作為引數,首先要明白他的型別,但是auto無法作為函式引數型別,使用1中獲取型別方法輸出為【Z4mainEUlvE_23】,根本不是型別,查閱資料,只能使用template模板來實現。
  1. template<typename T>  
  2. struct isFunctor : std::false_type {  
  3. };  
  4. template<typename L, typename R, typename... Args>  
  5. struct isFunctor<R (L::*)(Args...)> : std::true_type {  
  6. };  
  7. template<typename L>  
  8. struct isLambda : isFunctor<decltype(&L::operator())> {  
  9. };  
  10. template<typename L>  
  11. std::enable_if<isLambda<L>::value> check(L lambda) {  
  12.     cout << " lambda(1, 2) = " << lambda(1, 2) << lambda(1, 2);  
  13. }  
  14. int main() {  
  15.     auto fun = [&](int a, int b) {  
  16.         a++;  
  17.         b++;  
  18.         cout << a <<"."<< b << endl;  
  19.         return pow(a, b);  
  20.     };  
  21.     check(fun);  
  22.     return 0;  
  23. }  
  24. //輸出為: 2.3
  25. //       2.3
  26. //       lambda(1, 2) = 88
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
//lambda基礎
void lambda_one();
//sort中lambda例項
void lambda_two();
//lambda函式遞迴
void lambda_three();

int main()
{
 lambda_one();
 lambda_two();
 lambda_three();
 getchar();
 return 0;
}


void lambda_one()
{
    cout<<endl <<"------------沒有函式引數的lambda---------------------"<<endl;
    auto fun = [](){};
    auto fun1 = [](){cout <<"fun1"<<endl;};
    fun1();

    cout<<endl <<"------------for_each中使用簡單的lambda----------------"<<endl; 
    std::vector<int>  v(3,5);
    for_each(v.begin(),v.end(),[](int num){ cout << num << "\t";});

    cout<<endl <<"------------設定lambda的返回值型別--------------------"<<endl; 
    cout <<[](double a, double b){return a + b;}(1.4,2.5)<<endl; 
    cout <<[](double a, double b)->int{return a + b;}(1.4,2.5)<<endl;

    cout<<endl <<"------------lambda中的傳值----------------------------"<<endl;
    int x = 10;
    int y = 100;
    [=](double a, double b)mutable->int
    {
        cout <<"lambda:"<<(x = 100) << "\t" <<(y = 10)<<endl;
        return a + b;
    }(1.4,2.5);
    cout<<"main:" << x <<"\t"<< y <<endl;

    cout<<endl <<"------------lambda中的傳引用--------------------------"<<endl;
    [&x,&y](double a, double b)mutable->int
    {
        cout <<"lambda:"<<(x = 100) << "\t" <<(y = 10)<<endl;
        return a + b;
    }(1.4,2.5);
    cout<<"main:" << x <<"\t"<< y <<endl;

    cout<<endl <<"------------lambda中的傳引用和引用傳遞------------------"<<endl;
    //等號必須寫在前面,或者也可以[x,&y].
    //=表示,除了&y,其他所有的外部變數都可以按照值傳遞進行訪問。
    [=,&y](double a, double b)mutable->int
    {
        cout <<"lambda:"<<(x = 100) << "\t" <<(y = 10)<<endl;
        return a + b;
    }(1.4,2.5);
    cout<<"main:" << x <<"\t"<< y <<endl;
}

void lambda_two()
{
    //1.sort排序
    cout <<endl<<"------------sort排序中使用lambda------------------------"<<endl;
    int  a[8] = {6,8,3,4,9,2,7,1};
    sort(begin(a),end(a),[](const int &a ,const int &b)->bool{return a < b;});
    for_each(begin(a),end(a),[](const int &num){cout << num << "\t";});

    cout <<endl<<"---------------------------------------------------------"<<endl;

}

void lambda_three()
{
//2. (lambda遞迴)3個數返回最大的兩個數的和
    cout <<endl<<"------------lambda遞迴-----------------------------------"<<endl;
    function<int(int,int,int)> f = [&f](int a,int b,int c)->int
    {
        if (a<= b && a <= c)
        {
        return b + c;
        }
        return f(b,c,a);
    };
    cout << f(4,5,6)<<endl;
}