C++ Primer 筆記——lambda運算式

來源:互聯網
上載者:User

標籤:tab   檔案   div   out   lambda   color   推斷   socket   ram   

1.一個lambda運算式表示一個可調用的代碼單元,可以理解為一個未命名的內嵌函式,但是與函數不同,lambda運算式可能定義在函數內部。其形式如下:

[capture list] (parameter list) -> return type { function body }

  • capture list 是一個lambda所在函數中定義的局部變數的列表(通常為空白)
  • return type, parameter list 和 function body與任何普通函數一樣,分別表示傳回型別,參數列表和函數體
  • lambda必須使用尾置返回
  • 我們可以忽略參數列表和傳回型別,但必須永遠包含捕獲列表和函數體
  • 如果忽略傳回型別,lambda會從函數體推斷出傳回型別。
  • 如果lambda的函數體包含任何單一return語句之外的內容,且未指定傳回型別,則返回void
  • 捕獲列表只用於局部非static變數,lambda可以直接使用局部static變數和在它所在函數之外聲明的名字。
void test(){    int i = 1;    int j = 2;    auto f = [i, j](int base) -> int { return base + i + j; };    // i,j必須在捕獲列表裡面,這裡的傳回型別int其實可以省略    int k = f(0);    // k的結果為3}

 

2.當定義一個lambda時,編譯器產生一個與lambda對應的新的(未命名的)類類型。預設情況下這個類都包含一個對於該lambda所捕獲的變數的資料成員。類似任何普通類的資料成員,lambda的資料成員也在lambda對象建立時被初始化。

 

3.與傳值參數類似,採用值捕獲的前提是變數可以拷貝,與參數不同,被捕獲的變數的值是在lambda建立時拷貝,而不是調用時拷貝。

void test(){    int i = 10;    auto f = [i] {return i + 1; };    // 此時i的值就已經被拷貝了    int j = f();}

 

4.當以引用方式捕獲一個變數時,必須保證在lambda執行時變數是存在的。

void test(){    int i = 10;    auto f = [&i] {return ++i; };    int j = f();    // 此時i等於11}

 

5.在捕獲列表中寫一個 &或= 可以告訴編譯器我們想採用值捕獲還是引用捕獲,這種方法叫做隱式捕獲。

void test(){    int i = 10;    auto f = [&] {return ++i; };    // 採用引用捕獲    int j = f();    }


6.我們也可以混合使用值捕獲或者引用捕獲。當使用混合方式的時候,顯示捕獲的方式不可以與隱式捕獲的方式相同。

void test(){    int i = 10;    int j = 9;    auto f = [=, &i] {i++; return i + j; };    // i採用引用捕獲,其他採用值捕獲    int k = f();    // k等於20}

 

7.預設情況下,對於一個值被拷貝的變數,lambda不會改變其值,如果我們希望能改變一個被捕獲的變數的值,就必須在參數列表首加上mutable。

void test(){    int i = 10;    auto f = [i] (){return ++i; };    // 錯誤,不可以改變i的值    auto f1 = [i] () mutable {return ++i; };    // 正確}

 

8.bind函數(標頭檔 functional中)可以看作一個通用的函數適配器,它接受一個可調用對象,產生一個新的可調用對象來適應原對象的參數列表。調用bind的一般形式為:

auto newCallable = bind(callable, arg);

void test(int i, int j){    std::cout << i - j << std::endl;}auto test0 = std::bind(test, 5, 1);test0();    // 結果4auto test1 = std::bind(test, std::placeholders::_1, 5, std::placeholders::_2, 1);    // 錯誤,不可以這麼寫test1();    auto test2 = std::bind(test, std::placeholders::_1, 5);test2(1);    // 結果-4auto test3 = std::bind(test, std::placeholders::_1, std::placeholders::_2);test3(3, 2);    // 結果1auto test4 = std::bind(test, std::placeholders::_2, std::placeholders::_1);    // 參數順序可以重排test4(3, 2);    // 結果-1auto test5 = std::bind(test, 1, std::placeholders::_1);        // 注意這個預留位置占的是test5()的參數位置,而不是test()的test5(5);    // 結果-4

以上代碼請注意命名空間,否則會和socket的bind函數產生二義性。

9.如果我們想綁定的參數無法拷貝,或者我們想引用時應該使用ref函數。

void test(int& i, int j){    std::cout << i - j << std::endl;}int i = 5;auto test0 = std::bind(test, std::ref(i), 1);test0();    // 結果4


 

C++ Primer 筆記——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.