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
  1. class?A??
  2. {??
  3. public:??
  4. ????int?i_?=?0;??
  5. ??????
  6. ????void?func(int?x,int?y){??
  7. ????????auto?x1?=?[]?{?return?i_;?};?????????????????????????????//error,沒有捕獲外部變量??
  8. ????????auto?x2?=?[=]?{?return?i_?+?x?+?y;?};???????????????//OK??
  9. ????????auto?x3?=?[&]?{?return?i_?+?x?+?y;?};???????????????//OK??
  10. ????????auto?x4?=?[this]?{?return?i_;?};????????????????????????//OK??
  11. ????????auto?x5?=?[this]?{?return?i_?+?x?+?y;?};????????????//error,沒有捕獲x,y??
  12. ????????auto?x6?=?[this,?x,?y]?{?return?i_?+?x?+?y;?};????//OK??
  13. ????????auto?x7?=?[this]?{?return?i_++;?};???????????????????//OK??
  14. };??
  15. ??
  16. int?a=0?,?b=1;??
  17. auto?f1?=?[]?{?return?a;?};????????????????????????????//error,沒有捕獲外部變量??????
  18. auto?f2?=?[&]?{?return?a++?};??????????????????????//OK??
  19. auto?f3?=?[=]?{?return?a;?};?????????????????????????//OK??
  20. auto?f4?=?[=]?{return?a++;?};?????????????????????//error,a是以復制方式捕獲的,無法修改??
  21. auto?f5?=?[a]?{?return?a+b;?};?????????????????????//error,沒有捕獲變量b??
  22. auto?f6?=?[a,?&b]?{?return?a?+?(b++);?};??????//OK??
  23. auto?f7?=?[=,?&b]?{?return?a?+?(b++);?};?????//OK??


?注意的細節:

1.

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

[cpp]?view plain?copy
  1. int?a?=?0;??
  2. auto?f?=?[=]?{?return?a;?};??
  3. ??
  4. a+=1;??
  5. ??
  6. cout?<<?f()?<<?endl;???????//輸出0??
  7. ??
  8. ??
  9. int?a?=?0;??
  10. auto?f?=?[&a]?{?return?a;?};??
  11. ??
  12. a+=1;??
  13. ??
  14. cout?<<?f()?<<endl;???????//輸出1??


2.

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

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

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

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


3.

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

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


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

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

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


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384206.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384206.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384206.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Cutting Codeforces Round #493 (Div. 2)

Cutting There are a lot of things which could be cut — trees, paper, “the rope”. In this problem you are going to cut a sequence of integers. There is a sequence of integers, which contains the equal number of even and odd numbers. Given a limited bud…

Enum、Stream

Enum 其常見用法見&#xff1a;https://cloud.tencent.com/developer/section/1116852 在sort時&#xff0c;如果要獲得穩定的排序結果&#xff0c;要使用< 而不是 <。 Stream Stream是延遲處理的&#xff0c;而Enum是貪婪的&#xff0c;則意味著傳給它一個收集&#xff…

linux網絡編程之posix 線程(三):posix 匿名信號量與互斥鎖 示例生產者--消費者問題

http://blog.csdn.net/jnu_simba/article/details/9123603 一、posix 信號量 信號量的概念參見這里。前面也講過system v 信號量&#xff0c;現在來說說posix 信號量。 system v 信號量只能用于進程間同步&#xff0c;而posix 信號量除了可以進程間同步&#xff0c;還可以線程間…

洛谷P1080-國王游戲-貪心+高精度

P1080-國王游戲 啊啊啊&#xff0c;剛才已經寫了一次了&#xff0c;但是Edge瀏覽器不知道為什么卡住了&#xff0c;難受。 好吧&#xff0c;其實是一道可做題&#xff0c;分析得到的貪心策略就是就是將a * b小的放在前面&#xff08;其他的懶得說了&#xff09;&#xff0c;主要…

字符串與二進制

單引號字符串會被表示成整數值列表。 &#xff1f;c返回字符 c 的整數編碼。下面這個例子用于解析字符列表表示法&#xff0c;該表示法用于表示一個任意的有符號的十進制數據。 defmodule Parse dodef number([ ?- | tail ]) do_number_digits(tail, 0) * -1enddef number([ ?…

P1092蟲食算-深度優先搜索+玄學剪枝

P1092蟲食算 這道題的思想并不復雜&#xff0c;可是難點在于各種玄學剪枝。在仔細研究了題解大佬的剪枝原理后終于氵了過去。 先上代碼&#xff1a; #include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int MAXN100; int n…

多進程

使用spawn創建一個新進程&#xff0c;其第一個參數是模塊名、第二個參數是函數名、第三個參數是參數列表。spawn會返回一個進程標識符&#xff0c;通常叫做PID。 defmodule Spawn1 dodef greet doreceive do{sender, msg} ->send sender, { :ok, "Hello #{msg}" }…

Linux socket編程(二) 服務器與客戶端的通信

http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html上一篇寫了對套接字操作的封裝&#xff0c;這一節使用已封裝好的Socket類實現服務器與客戶端的通信&#xff08;Socket的定義見上篇Socket.h) 服務器端&#xff1a; ServerSocket.h #ifndef SERVERSOCKET_H #defin…

OTP服務器

defmodule Sequence.Server douse GenServerdef handle_call( :next_number, _from, current_number) do{ :reply, current_number, current_number 1}  #reply告訴OTP將第二個元素返回給客戶端end end use的效果將OTP GenServer的行為添加到當前模塊。這樣它就可以處理所有…

洛谷P1040-加分二叉樹-dp+二叉樹

P1040-加分二叉樹 這道題放在深度優先搜索的訓練題中&#xff0c;可是我實在沒有看出來應該怎么搜索。看了題解以后才看出來是一個很簡單的dp(我果然還是太菜了) 看出dp并且算出來最大的分數不是很復雜&#xff0c;關鍵是輸出給定中序遍歷序列的二叉樹的先序遍歷&#xff0c;要…

UNIX網絡編程:I/O復用技術(select、poll、epoll)

http://blog.csdn.net/dandelion_gong/article/details/51673085 Unix下可用的I/O模型一共有五種&#xff1a;阻塞I/O 、非阻塞I/O 、I/O復用 、信號驅動I/O 、異步I/O。此處我們主要介紹第三種I/O符復用。 I/O復用的功能&#xff1a;如果一個或多個I/O條件滿足&#xff08;輸…

解決iex -S mix報錯

執行iex -S mix命令的時候會遇到如下錯誤&#xff1a; 執行 mix deps.get 然后就可以運行 iex -S mix了 其中&#xff0c;有可能會出現 按照其網站下載相應文件&#xff0c;復制到項目根目錄下&#xff0c;然后執行命令&#xff08;mix local.rebar rebar ./rebar&#xff09;即…

貪心算法——選擇不相交區間問題

題目描述&#xff1a;設有n個活動的集合&#xff0c;其中每個活動都要求使用同一個資源&#xff0c;而在同一時間內只有一個活動能夠使用這一資源&#xff0c;每個活動i都有一個要求使用該資源的起始時間si和一個結束時間fi(si<fi)&#xff0c;如果選擇了活動i&#xff0c;則…

Anker—工作學習筆記

http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html 1、基本知識 epoll是在2.6內核中提出的&#xff0c;是之前的select和poll的增強版本。相對于select和poll來說&#xff0c;epoll更加靈活&#xff0c;沒有描述符限制。epoll使用一個文件描述符管理多個描述符&am…

Supervisor監控

可參考&#xff1a;https://www.cnblogs.com/wang_yb/archive/2016/06/08/5564459.html &#xff1a;https://segmentfault.com/a/1190000007379204 轉載于:https://www.cnblogs.com/lr1402585172/p/11551488.html

深度搜索剪枝——數的劃分

【題目描述】將整數n分成k份&#xff0c;且每份不能為空&#xff0c;問有多少種分法&#xff1f; 【輸入格式】兩個整數n,m(6<n<200,2<m<6) 【輸出格式】輸出不同的分法數 【樣例輸入】7 3 【樣例輸出】4 對于這種搜索題&#xff0c;關鍵就在于剪枝&#xff1a;確定…

Linux網絡編程——tcp并發服務器(I/O復用之select

http://blog.csdn.net/lianghe_work/article/details/46519633 與多線程、多進程相比&#xff0c;I/O復用最大的優勢是系統開銷小&#xff0c;系統不需要建立新的進程或者線程&#xff0c;也不必維護這些線程和進程。 代碼示例&#xff1a; [csharp] view plaincopy #include &…

ets

:ets.new(table_name, pattern) 第一個參數是表名&#xff0c;第二個參數是表的設置選項。 :set  一個key&#xff0c;一個數據&#xff0c;無序 :ordered_set  一個key&#xff0c;一個數據&#xff0c;有序&#xff1b; 1 1.0 :bag  一個key&#xff0c;多個數據&…

貪心算法-區間選點問題-種樹

【題目描述】一條街道的一邊有幾座房子。因為環保原因居民想要在路邊種些樹&#xff0c;路邊的地區被分割成n塊&#xff0c;并被編號為1~n。每塊大小為一個單位尺寸且最多可總一棵樹。每個居民想在門前種些樹并制定了三個數b,e,t&#xff0c;這三個數代表居民想在b和e之間最少種…

ets注意事項

當表類型為 :set 時&#xff0c;使用 :ets.first 和 :ets.last 會獲取到同一個 key。將表類型換為 :oedered_set 就可以避免這種情況 轉載于:https://www.cnblogs.com/lr1402585172/p/11599219.html