日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C++11 学习笔记 lambda表达式

發布時間:2023/11/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++11 学习笔记 lambda表达式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/fjzpdkf/article/details/50249287

 lambda表達式是C++11最重要也最常用的一個特性之一。lambda來源于函數式編程的概念,也是現代編程語言的一個特點。

?

一.函數式編程簡介

定義:簡單說,“函數式編程”是一種“編程范式”。它屬于“結構化編程”的一種,主要思想是把運算過程盡量寫成一系列嵌套的函數調用。

?

特點:

1).函數是“第一等公民”,可以賦值給他其他變量,也可以做為參數,返回值。

2).只用“表達式”,不用“語句”。“表達式”是一個單純的運算過程,總是有返回值;“語句”是執行某種操作,沒有返回值。

3).沒有副作用。函數保持獨立,所有功能就是返回一個新的值,其他什么都不做,不修改外部變量的值。

4).引用透明。函數的運行不依賴于外部變量或“狀態”,只依賴于輸入的參數,只要參數相同,返回值就相同。

?

二.lambda表達式

lambda表達式有如下優點:

1).聲明式編程風格:就地匿名定義目標函數或函數對象,不需要額外寫一個命名函數或者函數對象。以更直接的方式去寫程序,好的可讀性和可維護性。

2).簡潔:不需要額外再寫一個函數或者函數對象,避免了代碼膨脹和功能分散,讓開發者更加集中精力在手邊的問題,同時也獲取了更高的生產率。

3).在需要的時間和地點實現功能閉包,使程序更靈活。

?

lambda表達式的語法歸納如下:

[ caputrue ] ( params ) opt -> ret { body; };

1).capture是捕獲列表;

2).params是參數表;(選填)

3).opt是函數選項;可以填mutable,exception,attribute(選填)

mutable說明lambda表達式體內的代碼可以修改被捕獲的變量,并且可以訪問被捕獲的對象的non-const方法。

exception說明lambda表達式是否拋出異常以及何種異常。

attribute用來聲明屬性。

4).ret是返回值類型。(選填)

5).body是函數體。

?

捕獲列表:lambda表達式的捕獲列表精細控制了lambda表達式能夠訪問的外部變量,以及如何訪問這些變量。

1).[]不捕獲任何變量。

2).[&]捕獲外部作用域中所有變量,并作為引用在函數體中使用(按引用捕獲)。

3).[=]捕獲外部作用域中所有變量,并作為副本在函數體中使用(按值捕獲)。

4).[=,&foo]按值捕獲外部作用域中所有變量,并按引用捕獲foo變量。

5).[bar]按值捕獲bar變量,同時不捕獲其他變量。

6).[this]捕獲當前類中的this指針,讓lambda表達式擁有和當前類成員函數同樣的訪問權限。如果已經使用了&或者=,就默認添加此選項。捕獲this的目的是可以在lamda中使用當前類的成員函數和成員變量。

[cpp]?view plain?copy
  • class?A??
  • {??
  • public:??
  • ????int?i_?=?0;??
  • ??????
  • ????void?func(int?x,int?y){??
  • ????????auto?x1?=?[]?{?return?i_;?};?????????????????????????????//error,沒有捕獲外部變量??
  • ????????auto?x2?=?[=]?{?return?i_?+?x?+?y;?};???????????????//OK??
  • ????????auto?x3?=?[&]?{?return?i_?+?x?+?y;?};???????????????//OK??
  • ????????auto?x4?=?[this]?{?return?i_;?};????????????????????????//OK??
  • ????????auto?x5?=?[this]?{?return?i_?+?x?+?y;?};????????????//error,沒有捕獲x,y??
  • ????????auto?x6?=?[this,?x,?y]?{?return?i_?+?x?+?y;?};????//OK??
  • ????????auto?x7?=?[this]?{?return?i_++;?};???????????????????//OK??
  • };??
  • ??
  • int?a=0?,?b=1;??
  • auto?f1?=?[]?{?return?a;?};????????????????????????????//error,沒有捕獲外部變量??????
  • auto?f2?=?[&]?{?return?a++?};??????????????????????//OK??
  • auto?f3?=?[=]?{?return?a;?};?????????????????????????//OK??
  • auto?f4?=?[=]?{return?a++;?};?????????????????????//error,a是以復制方式捕獲的,無法修改??
  • auto?f5?=?[a]?{?return?a+b;?};?????????????????????//error,沒有捕獲變量b??
  • auto?f6?=?[a,?&b]?{?return?a?+?(b++);?};??????//OK??
  • auto?f7?=?[=,?&b]?{?return?a?+?(b++);?};?????//OK??


  • ?注意的細節:

    1.

      一個容易出錯的細節是lambda表達式的延遲調用,lambda表達式按值捕獲了所有外部變量。在捕獲的一瞬間,a的值就已經被復制了。如果希望lambda表達式在調用時能即時訪問外部變量,我們應當使用引用方式捕獲。

    [cpp]?view plain?copy
  • int?a?=?0;??
  • auto?f?=?[=]?{?return?a;?};??
  • ??
  • a+=1;??
  • ??
  • cout?<<?f()?<<?endl;???????//輸出0??
  • ??
  • ??
  • int?a?=?0;??
  • auto?f?=?[&a]?{?return?a;?};??
  • ??
  • a+=1;??
  • ??
  • cout?<<?f()?<<endl;???????//輸出1??


  • 2.

      雖然按值捕獲的變量值均補復制一份存儲在lambda表達式變量中, 修改他們也并不會真正影響到外部,但我們卻仍然無法修改它們。

      那么如果希望去修改按值捕獲的外部變量,需要顯示指明lambda表達式為mutable。

      需要注意:被mutable修飾的lambda表達式就算沒有參數也要寫明參數列表。
      原因:lambda表達式可以說是就地定義仿函數閉包的“語法糖”。它的捕獲列表捕獲住的任何外部變量,最終均會變為閉包類型的成員變量。按照C++標準,lambda表達式的operator()默認是const的,一個const成員函數是無法修改成員變量的值的。而mutable的作用,就在于取消operator()的const。

    [cpp]?view plain?copy
  • int?a?=?0;??
  • auto?f1?=?[=]?{?return?a++;?};???????????????????????//error??
  • auto?f2?=?[=]?()?mutable?{?return?a++;?};???????//OK??

  • 3.

      沒有捕獲變量的lambda表達式可以直接轉換為函數指針,而捕獲變量的lambda表達式則不能轉換為函數指針。原因可以參考2中的原因。

    [cpp]?view plain?copy
  • typedef?void(*Ptr)(int*);??
  • ??
  • Ptr?p?=?[](int*?p)?{?delete?p;?};??????????????//OK??
  • Ptr?p1?=?[&]?(int*?p)?{?delete?p;?};?????????//error??


  • 最后,兩個實際應用到lambda表達式的代碼。

    [cpp]?view plain?copy
  • std::vector<int>?v?=?{?1,?2,?3,?4,?5,?6?};??
  • int?even_count?=?0;??
  • for_each(v.begin(),?v.end(),?[&even_count](int?val){??
  • ????if(!(val?&?1)){??
  • ????????++?even_count;??
  • ????}??
  • });??
  • std::cout?<<?"The?number?of?even?is?"?<<?even_count?<<?std::endl;??

  • [cpp]?view plain?copy
  • int?count?=?std::count_if(?coll.begin(),?coll.end(),?[](int?x){?return?x?>?10;?});??
  • ??
  • int?count?=?std::count_if(?coll.begin(),?coll.end(),?[](int?x){?return?x?<?10;?});??
  • ??
  • int?count?=?std::count_if(?coll.begin(),?coll.end(),?[](int?x){?return?x?>?5?&&?x<10;?});??


  • 總結

    以上是生活随笔為你收集整理的C++11 学习笔记 lambda表达式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。