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

2021-06-23 09:05:42 字數 4359 閱讀 1841



宣告:本文參考了alex allain的文章

加入了自己的理解,不是簡單的翻譯

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

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

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

[cpp]view plain

copy

print?

#include 

using

namespace std;  

int main()  

;  func(); // now call the function

}  

#include using namespace std;

int main()

; func(); // now call the function

}

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

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

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

[cpp]view plain

copy

print?

() -> int   

() -> int

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

[cpp]view plain

copy

print?

[captures] (params) -> ret   

[captures] (params) -> ret

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

[cpp]view plain

copy

print?

#include 

#include 

class addressbook  

}  return results;  

}  private:  

std::vector_addresses;  

};  

#include #include class addressbook

}return results;

}private:

std::vector_addresses;

};

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

[cpp]view plain

copy

print?

addressbook global_address_book;  

vectorfindaddressesfromorgs ()  

);  

}  

addressbook global_address_book;

vectorfindaddressesfromorgs ()

);}

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

[cpp]view plain

copy

print?

const string& addr  

const string& addr

返回值是bool型別。

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

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

[cpp]view plain

copy

print?

// 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)    

);  

// 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

print?

vector v;  

v.push_back( 1 );  

v.push_back( 2 );  

//...

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

vectorv;

v.push_back( 1 );

v.push_back( 2 );

//...

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

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

[cpp]view plain

copy

print?

vector v;  

v.push_back( 1 );  

v.push_back( 2 );  

//...

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

);  

vectorv;

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函式(匿名函式)

c 11終於知道要在語言中加入匿名函式了。匿名函式在很多時候可以為編碼提供便利,這在下文會提到。很多語言中的匿名函式,如c 都是用lambda表示式實現的。lambda表示式又稱為lambda函式。我在下文中稱之為lambda函式。為了明白lambda函式的用處,請務必先搞明白c 中的自動型別推斷 ...

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

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