日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
編譯器如何實現(xiàn)lambda表達(dá)式?

[[404386]]

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計、網(wǎng)站制作服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)大武口免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了1000多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。

本文轉(zhuǎn)載自微信公眾號「程序喵大人」,作者程序喵大人。轉(zhuǎn)載本文請聯(lián)系程序喵大人公眾號。

lambda表達(dá)式在C++11中引入,用lambda表達(dá)式表示匿名函數(shù)非常方便,語法很簡單,而且可以使代碼更緊湊,更易于閱讀。

lambda表達(dá)式更適合定義小點的回調(diào)內(nèi)聯(lián)去傳遞給其他函數(shù),而不是在其他地方定義個完整的函數(shù)對象,并在其重載函數(shù)調(diào)用運算符中實現(xiàn)回調(diào)邏輯。所有的邏輯都在一個位置上,容易理解和維護(hù),lambda表達(dá)式可以接收參數(shù),可返回值,可模板化,可通過值或引用的方式訪問外面的變量,相當(dāng)?shù)撵`活。

關(guān)于lambda表達(dá)式的使用,我之前介紹過,可以看這篇文章搞定c++11新特性std::function和lambda表達(dá)式,這里一筆帶過:

 
 
 
  1. auto lambda { []{ cout << "Hello \n"; } }; 
  2. lambda(); 

那這個lambda表達(dá)式是如何實現(xiàn)的呢?

編譯器會將lambda表達(dá)式自動轉(zhuǎn)換為函數(shù)對象,編譯器會為此生成個唯一的命名。上面的示例會自動的轉(zhuǎn)換成下面這樣的函數(shù)對象,注意函數(shù)調(diào)用運算符是個const方法,返回類型是auto,這方便編譯器根據(jù)方法體自動推導(dǎo)出返回類型。

 
 
 
  1. class CompilerGeneratedName { 
  2.     public: 
  3.         auto operator()() const { cout << "Hello \n"; } 
  4. }; 

編譯器生成的lambda閉包名字會是一些奇怪的名子,例如__Lambda_21Za等,我們沒法知道這個名字,我們也不需要知道這個名字。

lambda表達(dá)式可以接收參數(shù),參數(shù)在圓括號之間指定,就像普通函數(shù)一樣,下面是例子:

 
 
 
  1. auto lambda { 
  2.     [](int value){ cout << "The value is " << value << endl; } }; 
  3. lambda(42); 

如果lambda表達(dá)式不接收任何參數(shù),可以指定空括號或者直接省略括號。

編譯器會將上面的lambda表達(dá)式自動轉(zhuǎn)換為下面這樣:

 
 
 
  1. class CompilerGeneratedName { 
  2.     public: 
  3.         auto operator()(int value) const { 
  4.             cout << "The value is " << value << endl; } 
  5. }; 

lambda表達(dá)式可以返回值,返回類型在箭頭后面指定,稱為尾返回類型,看代碼:

 
 
 
  1. auto lambda { [](int a, int b) -> { return a + b; } }; 
  2. int sum = lambda(11, 22); 

編譯器轉(zhuǎn)成這樣:

 
 
 
  1. class CompilerGeneratedName { 
  2.     public: 
  3.         auto operator()(int a, int b) const { return a + b; } 
  4. }; 

那能捕獲變量的lambda表達(dá)式是怎么實現(xiàn)的呢?

比如下面的lambda表達(dá)式:

 
 
 
  1. double data { 1.234 }; 
  2. auto lambda { [data]{ cout << "Data = " << data << endl; } } 

捕獲的變量會變?yōu)閘ambda閉包的數(shù)據(jù)成員,值捕獲的變量被拷貝到仿函數(shù)的數(shù)據(jù)成員中,編譯器的行為是這樣:

 
 
 
  1. class CompilerGeneratedName 
  2.     public: 
  3.         CompilerGeneratedName(const double& d) : data { d } {} 
  4.         auto operator()() const { cout << "Data = " << data << endl; } 
  5.     private: 
  6.         double data; 
  7. }; 

還有泛型lambda表達(dá)式:

 
 
 
  1. auto areEqual { [](const auto& value1, const auto& value2) { 
  2.     return value1 == value2; } }; 
  3.  
  4. vector values1 { 2, 5, 6, 9, 10, 1, 1 }; 
  5. vector values2 { 4, 4, 2, 9, 0, 3, 1 }; 
  6. findMatches(values1, values2, areEqual, printMatch); 

編譯器會轉(zhuǎn)換成這樣:

 
 
 
  1. class CompilerGeneratedName { 
  2.     public: 
  3.         template  
  4.         auto operator()(const T1& value1, const T2& value2) const 
  5. { return value1 == value2; } 
  6. }; 

如果findMatches()函數(shù)中的參數(shù)是其他類型,那么areEqual泛型表達(dá)式不需要任何更改就可以直接繼續(xù)使用。

聊完了編譯器怎么實現(xiàn)的lambda表達(dá)式,下面介紹下lambda表達(dá)式的捕獲方式。

捕獲方式

有兩種方法從閉包作用域捕獲所有變量,稱為默認(rèn)捕獲:

  • [=] 值捕獲所有變量
  • [&]引用捕獲所有變量
  • 注意:
  • 使用引用方式捕獲變量時,必須確保引用在lambda表達(dá)式執(zhí)行期間是合法的。
  • 當(dāng)使用默認(rèn)捕獲時,通過值(=)或引用(&),只有那些在lambda 表達(dá)式中真正使用的變量才會被捕獲,未使用的變量不會被捕獲。
  • 不建議使用默認(rèn)捕獲,即使默認(rèn)捕獲只捕獲那些在lambda 表達(dá)式主體中真正使用的變量,通過使用=默認(rèn)捕獲,可能會意外的導(dǎo)致高代價的拷貝,通過使用&默認(rèn)捕獲,可能意外的在閉包作用域中修改變量,建議明確指定想要捕獲哪些變量以及捕獲方式。

再注意:全局變量總是通過引用捕獲,例如在下面的代碼中,默認(rèn)捕獲用于按值捕獲所有內(nèi)容,然而全局變量global其實是通過引用捕獲的,在執(zhí)行l(wèi)ambda 后它的值被更改。

 
 
 
  1. int global { 42 }; 
  2. int main() { 
  3.     auto lambda { [=] { global = 2; } }; 
  4.     lambda(); 
  5.     // 這里global是2! 

不允許像下面這樣顯式捕獲全局變量,這樣編譯會失?。?/p>

 
 
 
  1. auto lambda { [global] { global = 2; } }; // error 

所以,建議不要使用全局變量。

對于不捕獲任何內(nèi)容的lambda表達(dá)式,編譯器自動提供轉(zhuǎn)換運算符,將lambda 表達(dá)式轉(zhuǎn)換為函數(shù)指針。這樣的lambda表達(dá)式可作為參數(shù)傳遞給其他函數(shù)。

在C++20中關(guān)于lambda表達(dá)式也做了一些更新,可以模板化lambda表達(dá)式,也可以默認(rèn)構(gòu)造、拷貝和賦值lambda表達(dá)式,像下面這樣:

 
 
 
  1. auto lambda { [](int a, int b) { return a + b; } }; 
  2. decltype(lambda) lambda2; // 默認(rèn)構(gòu)造 
  3. auto copy { lambda }; // 拷貝構(gòu)造 
  4. copy = lambda2; // 拷貝賦值 

 

這不是本文的主題,就不過多介紹了。

 


標(biāo)題名稱:編譯器如何實現(xiàn)lambda表達(dá)式?
轉(zhuǎn)載源于:http://www.dlmjj.cn/article/dhgoeog.html