C 11新特性 Lambda函式(匿名函式)

2021-06-17 20:50:47 字數 3099 閱讀 7203

c++11終於知道要在語言中加入匿名函式了。匿名函式在很多時候可以為編碼提供便利,這在下文會提到。很多語言中的匿名函式,如c++,都是用lambda表示式實現的。lambda表示式又稱為lambda函式。我在下文中稱之為lambda函式。

為了明白lambda函式的用處,請務必先搞明白c++中的自動型別推斷:

我們可以這樣定義乙個lambda函式:

[cpp]view plain

copy

#include 

using

namespace

std;  

intmain()  

;  func(); // now call the function

}  

其中func就是乙個lambda函式。我們使用auto來自動獲取func的型別,這個非常重要。定義好lambda函式之後,就可以當這場函式來使用了。

其中 [ ] 表示接下來開始定義lambda函式,中括號中間有可能還會填引數,這在後面介紹。之後的()填寫的是lambda函式的引數列表{}中間就是函式體了。

正常情況下,只要函式體中所有return都是同乙個型別的話,編譯器就會自行判斷函式的返回型別。也可以顯示地指定lambda函式的返回型別。這個需要用到函式返回值後置的功能,比如這個例子:

[cpp]view plain

copy

() -> 

int  

所以總的來說lambda函式的形式就是:

[cpp]view plain

copy

[captures] (params) -> ret   

假設你設計了乙個位址簿的類。現在你要提供函式查詢這個位址簿,可能根據姓名查詢,可能根據位址查詢,還有可能兩者結合。要是你為這些情況都寫個函式,那麼你一定就跪了。所以你應該提供乙個介面,能方便地讓使用者自定義自己的查詢方式。在這裡可以使用lambda函式來實現這個功能。

[cpp]view plain

copy

#include 

#include 

class

addressbook  

}  return

results;  

}  private

:  std::vector_addresses;  

};  

從上面**可以看到,findmatchingaddressses函式提供的引數是func型別,這是乙個泛型型別。在使用過程中應該傳入乙個函式,然後分別對位址簿中每乙個entry執行這個函式,如果返回值為真那麼表明這個entry符合使用者的篩選要求,那麼就應該放入結果當中。那麼這個func型別的引數如何傳入呢?

[cpp]view plain

copy

addressbook global_address_book;  

vectorfindaddressesfromorgs ()  

);  

}  

可以看到,我們在呼叫函式的時候直接定義了乙個lambda函式。引數型別是

[cpp]view plain

copy

const

string& addr  

返回值是bool型別。

如果使用者要使用不同的方式查詢的話,只要定義不同的lambda函式就可以了。

在上述例子中,lambda函式使用的都是函式體的引數和它內部的資訊,並沒有使用外部資訊。我們設想這樣的乙個場景,我們從鍵盤讀入乙個名字,然後用lambda函式定義乙個匿名函式,在位址簿中查詢有沒有相同名字的人。那麼這個lambda函式勢必就要能使用外部block中的變數,所以我們就得使用變數擷取功能(variable capture)。

[cpp]view plain

copy

// read in the name from a user, which we want to search

string name;  

cin>> name;  

return

global_address_book.findmatchingaddresses(   

// notice that the lambda function uses the the variable 'name'

[&] (const

string& addr)    

);  

從上述**看出,我們的lambda函式已經能使用外部作用域中的變數name了。這個lambda函式乙個最大的區別是中間加入了&符號。這就告訴了編譯器,要進行變數擷取。這樣lambda函式體就可以使用外部變數。如果不加入任何符號,編譯器就不會進行變數擷取。

下面是各種變數擷取的選項:

lambda函式的引入為stl的使用提供了極大的方便。比如下面這個例子,當你想便利乙個vector的時候,原來你得這麼寫:

[cpp]view plain

copy

vector<

int> v;  

v.push_back( 1 );  

v.push_back( 2 );  

//...

for( auto itr = v.begin(), end = v.end(); itr != end; itr++ )  

現在有了lambda函式你就可以這麼寫

[cpp]view plain

copy

vector<

int> v;  

v.push_back( 1 );  

v.push_back( 2 );  

//...

for_each( v.begin(), v.end(),  (int

val)  

);  

而且這麼寫了之後執行效率反而提高了。因為編譯器有可能使用」迴圈展開「來加速執行過程(計算機系統結構課程中學的)。

這個ppt詳細介紹了如何使用lambda表示式和stl

**:

c 11新特性 lambda函式

lambda歷史悠久,在數理邏輯和電腦科學領域,lambda被用來表示一種匿名函式這種匿名函式代表了一種 演算 lambda calculus 但是在c 領域直到c 11才引入lambda表示式,本文先打算從lambda函式入手 後續會繼續從lambda與仿函式 lambda基礎應用 lambda的...

C 11新特性 Lambda函式(匿名函式)

宣告 本文參考了alex allain的文章 加入了自己的理解,不是簡單的翻譯 c 11終於知道要在語言中加入匿名函式了。匿名函式在很多時候可以為編碼提供便利,這在下文會提到。很多語言中的匿名函式,如c 都是用lambda表示式實現的。lambda表示式又稱為lambda函式。我在下文中稱之為lam...

C 11新特性 Lambda函式(匿名函式)

宣告 本文參考了alex allain的文章 加入了自己的理解,不是簡單的翻譯 c 11終於知道要在語言中加入匿名函式了。匿名函式在很多時候可以為編碼提供便利,這在下文會提到。很多語言中的匿名函式,如c 都是用lambda表示式實現的。lambda表示式又稱為lambda函式。我在下文中稱之為lam...