成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

編譯器如何實現lambda表達式?

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

[[404386]]

本文轉載自微信公眾號「程序喵大人」,作者程序喵大人。轉載本文請聯系程序喵大人公眾號。

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

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

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

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

那這個lambda表達式是如何實現的呢?

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

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

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

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

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

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

編譯器會將上面的lambda表達式自動轉換為下面這樣:

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

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

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

編譯器轉成這樣:

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

那能捕獲變量的lambda表達式是怎么實現的呢?

比如下面的lambda表達式:

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

捕獲的變量會變為lambda閉包的數據成員,值捕獲的變量被拷貝到仿函數的數據成員中,編譯器的行為是這樣:

  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表達式:

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

編譯器會轉換成這樣:

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

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

聊完了編譯器怎么實現的lambda表達式,下面介紹下lambda表達式的捕獲方式。

捕獲方式

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

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

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

  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 

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

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

在C++20中關于lambda表達式也做了一些更新,可以模板化lambda表達式,也可以默認構造、拷貝和賦值lambda表達式,像下面這樣:

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

 

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

 

責任編輯:武曉燕 來源: 程序喵大人
相關推薦

2025-03-06 08:16:08

lambda表達式變量

2009-08-10 09:41:07

.NET Lambda

2009-09-11 09:48:27

Linq Lambda

2009-09-09 13:01:33

LINQ Lambda

2009-09-15 15:18:00

Linq Lambda

2022-12-05 09:31:51

接口lambda表達式

2012-06-26 10:03:58

JavaJava 8lambda

2009-08-27 09:44:59

C# Lambda表達

2009-09-15 17:30:00

Linq Lambda

2009-09-17 09:44:54

Linq Lambda

2009-09-17 10:40:22

Linq Lambda

2024-03-25 13:46:12

C#Lambda編程

2009-10-12 10:11:08

Lambda表達式編寫

2009-04-29 09:05:59

Lambda抽象代表.NET

2009-08-27 09:57:50

C# Lambda表達

2009-08-31 17:11:37

Lambda表達式

2009-09-17 09:09:50

Lambda表達式Linq查詢

2009-08-26 16:17:23

C# Lambda表達

2013-04-07 15:44:26

Java8Lambda

2009-09-09 17:14:17

Linq lambda
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久影院色老大 | 久久久久久久久99精品 | 婷婷丁香综合网 | 91在线看 | 国产欧美一区二区三区国产幕精品 | 做a的各种视频 | 久久九| 成人亚洲视频 | 午夜欧美a级理论片915影院 | av中文在线 | www97影院| 午夜小视频在线播放 | 久久久一二三区 | 国产99热精品 | 中文字幕在线一区 | 成人在线观看免费 | 精品日韩| 免费福利视频一区二区三区 | 国产一区二区在线观看视频 | 日韩电影免费观看中文字幕 | 国产一区在线免费观看视频 | 成人特区| 国产成人av免费看 | 天天干天天草 | 电影午夜精品一区二区三区 | 精品国产乱码一区二区三区 | 户外露出一区二区三区 | 日本三级电影免费 | 中文亚洲视频 | 免费在线观看毛片 | 日一区二区| 美女天堂av| 天堂免费看片 | 中文字幕亚洲视频 | www.成人免费视频 | 欧美91| 蜜桃黄网 | 国产一区二区三区 | 亚洲综合日韩精品欧美综合区 | 欧美一级一 | 欧美亚洲网站 |