C++中的Lambda運算式

來源:互聯網
上載者:User

標籤:amp   為什麼   包括   曆史   同名   區別   指標   space   錯誤   

一段簡單的Code

我也不是文藝的人,對於Lambda的曆史,以及Lambda與C++的那段淵源,我也不是很熟悉,技術人,講究拿代碼說事。

#include<iostream>using namespace std; int main(){    int a = 1;    int b = 2;     auto func = [=, &b](int c)->int {return b += a + c;};    return 0;}

 

基本文法

簡單來說,Lambda函數也就是一個函數,它的文法定義如下:

[capture](parameters) mutable ->return-type{statement}

1.[capture]:捕捉列表。捕捉列表總是出現在Lambda函數的開始處。實際上,[]是Lambda引出符。編譯器根據該引出符判斷接下來的代碼是否是Lambda函數。捕捉列表能夠捕捉上下文中的變數以供Lambda函數使用;

2.(parameters):參數列表。與普通函數的參數列表一致。如果不需要參數傳遞,則可以連同括弧“()”一起省略;

3.mutable:mutable修飾符。預設情況下,Lambda函數總是一個const函數,mutable可以取消其常量性。在使用該修飾符時,參數列表不可省略(即使參數為空白);

4.->return-type:傳回型別。用追蹤傳回型別形式聲明函數的傳回型別。我們可以在不需要傳回值的時候也可以連同符號”->”一起省略。此外,在傳回型別明確的情況下,也可以省略該部分,讓編譯器對傳回型別進行推導;

5.{statement}:函數體。內容與普通函數一樣,不過除了可以使用參數之外,還可以使用所有捕獲的變數。

與普通函數最大的區別是,除了可以使用參數以外,Lambda函數還可以通過捕獲列表訪問一些上下文中的資料。具體地,捕捉列表描述了上下文中哪些資料可以被Lambda使用,以及使用方式(以值傳遞的方式或引用傳遞的方式)。文法上,在“[]”包括起來的是捕捉列表,捕捉列表由多個捕捉項組成,並以逗號分隔。捕捉列表有以下幾種形式:

1.[var]表示值傳遞方式捕捉變數var;
2.[=]表示值傳遞方式捕捉所有父範圍的變數(包括this);
3.[&var]表示引用傳遞捕捉變數var;
4.[&]表示引用傳遞方式捕捉所有父範圍的變數(包括this);
5.[this]表示值傳遞方式捕捉當前的this指標。

上面提到了一個父範圍,也就是包含Lambda函數的語句塊,說通俗點就是包含Lambda的“{}”代碼塊。上面的捕捉列表還可以進行組合,例如:

1.[=,&a,&b]表示以引用傳遞的方式捕捉變數a和b,以值傳遞方式捕捉其它所有變數;
2.[&,a,this]表示以值傳遞的方式捕捉變數a和this,引用傳遞方式捕捉其它所有變數。

不過值得注意的是,捕捉列表不允許變數重複傳遞。下面一些例子就是典型的重複,會導致編譯時間期的錯誤。例如:

3.[=,a]這裡已經以值傳遞方式捕捉了所有變數,但是重複捕捉a了,會報錯的;
4.[&,&this]這裡&已經以引用傳遞方式捕捉了所有變數,再捕捉this也是一種重複。

關於Lambda那些奇葩的東西

#include<iostream>        using namespace std;                                int main()                {                             int j = 10;               auto by_val_lambda = [=]{ return j + 1; };    auto by_ref_lambda = [&]{ return j + 1; };    cout<<"by_val_lambda: "<<by_val_lambda()<<endl;    cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;                              ++j;                      cout<<"by_val_lambda: "<<by_val_lambda()<<endl;    cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;                              return 0;             }

程式輸出結果如下:

by_val_lambda: 11by_ref_lambda: 11by_val_lambda: 11by_ref_lambda: 12

你想到了嗎???那這又是為什麼呢?為什麼第三個輸出不是12呢?

在by_val_lambda中,j被視為一個常量,一旦初始化後不會再改變(可以認為之後只是一個跟父範圍中j同名的常量),而在by_ref_lambda中,j仍然在使用父範圍中的值。所以,在使用Lambda函數的時候,如果需要捕捉的值成為Lambda函數的常量,我們通常會使用按值傳遞的方式捕捉;相反的,如果需要捕捉的值成成為Lambda函數運行時的變數,則應該採用按引用方式進行捕捉。

C++中的Lambda運算式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.