[C++] Lambda表達式使用說明

前言:

c++ 11引入了Lambda表達式,即匿名函數,此語法極大地削減了某些場景下的代碼量。Lambda表達式是一個可執行對象,功能類似於函數,但是存在於函數內部,且僅能在函數內部訪問。

 

語法:

[捕獲列表](入參列表)[->返回值類型]{函數體}

捕獲列表不可爲空;

入參可爲空;

返回值爲空;

函數體不可爲空;

例如:

auto f  = []{return 40;}

auto f1 = [](int i)->int{ return i*10; }

 

限制:

Lambda定義在函數內,也只能使用函數內的局部變量,而且不是所有的都能用,只能用那些作爲捕獲列表傳遞給自己的。

例如:

void func()

{
    int i;
    string s;
    char c;

    auto f = [i,s]{
        //lambda body
        printf("s is -> %s",s.c_str());
        printf("i is -> %d",i);
        //printf("c is -> %c",c);        //這裏不能用c,因爲c不在捕獲列表中
    }

}

 

底層原理:

Lambda的底層原理是一個匿名類:

  • 這個類使用捕獲列表中的數據類型創建自己的成員變量;
  • 再重載operator()運算符,即讓自己是一個可調用類,operator()運算符的實現就是Lambda的函數體;
  • 參數列表爲operator()運算符的入參,即上一步中重載運算符的參數列表和入參列表一致;
  • 同理,返回值類型便是operator()運算符的返回值類型。

ps:捕獲列表可以不按值傳遞,可以傳引用和指針。

既然可以使值捕獲,也可以是引用捕獲,那麼如果是值捕獲模式,那麼要求捕獲列表中參數的類型一定是有拷貝構造的,這也是類類型作爲函數入參的必要條件。

 

隱式捕獲和全捕獲列表:

如果Lambda所處的函數中有很多局部變量,而這些變量全都要在Lambda中捕獲使用,那麼是不是就必須把這些變量全都寫到捕獲列表中了呢?這樣的話豈不是會寫很長的捕獲列表?

答案是否定的,我們可以通過隱式捕獲的方式指定當前函數的所有局部變量都可以在Lambda中使用,語法如下:

auto f = [=]{ return true; }           //f所處函數中的所有局部變量都按照 值傳遞 的方式作爲Lambda的捕獲列表

auto f = [&]{ return true; }           //f所處函數中的所有局部變量都按照 引用傳遞 的方式作爲Lambda的捕獲列表

問題又來了,如果想讓個別局部變量區別於其他的捕獲方式呢?比如其他局部變量都是 值捕獲, 但是局部變量 c 希望是引用捕獲,那麼就有:

void fun (){

       int i,j,k,l,d,m,f;

       char c;

       auto f = [=,&c] {

             int total = i+k+j+l+d+m+f;           //可以使用所有局部變量

             c = 'A';              //改變fun函數的局部變量c,因爲是引用捕獲,所以會影響原值
       }
}

同理,有:

auto f = [&,c] { ... }              //所有局部變量都是引用捕獲,僅c爲值捕獲

 

結語:

lambda的初衷是用來替代 容器泛型算法的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章