| 廣告聯系 | 簡體版 | 手機版 | 微信 | 微博 | 搜索:
歡迎您 游客 | 登錄 | 免費注冊 | 忘記了密碼 | 社交賬號注冊或登錄

首頁

新聞資訊

論壇

溫哥華地產

大溫餐館點評

溫哥華汽車

溫哥華教育

黃頁/二手

旅游
搜索:  

 論壇通告:  請不要上傳第三方有版權的照片,請尊重版權,謝謝   轉載新聞請務必注明出處,這些媒體請不要轉,謝謝   批評商家需要注意  
 個人空間: XY | 羅蓬特機器人 | NotmeL8 | 豬頭看世界 | 白龍王許道長 | 一襲絳襦落鵬城,疑似玄女下九天 | 花隨風 | 呂洪來的個人空間 | lxls | 靜觀雲卷雲舒 | 顧曉軍 | 客觀中立而實事求是,唯服理據而杜絕辱罵 | 逸言堂 | 格局 | 大溫房產和地產研究 | 我的退休生活 | 禪人俗事 | 湖裡湖塗 | 天涯逐夢 | My AI Tech Channel
 最新求助: 請問誰知道哪裡有賣理發的電動推子?   忽然有個疑問:戰爭時期,加拿大拿PR卡未入籍的永久居民會被強制服兵役嗎?   這個銀條   如何修改會員名?
 論壇轉跳:
     發帖回帖獲取加西鎊, 兌換精彩禮物

論壇首頁 -> IT人生

ZT:C++ Lambda 表達式使用詳解 (發表於10年前)



回復主題  圖片幻燈展示  增添帖子到書簽中  給帖子中的發貼者批量贈送獻花或者花籃    |##| -> |=|        發表新主題
閱讀上一個主題 :: 閱讀下一個主題  
作者 正文
webdriver
(只看此人)




文章 時間: 2014-10-20 17:17 引用回復
C++ 11 對LB的支持,對於喜歡Functional Programming的人來說,無疑是超好消息。它使得C++進入了和C#,JavaScript等現代流行的程序設計語言所代表的名人堂。

不熟悉LB本身的網友,可以看MSDN文章

msdn.microsoft.com/en-...93608.aspx ),我僅僅簡單地分析一下VC++中LB的用法,實現,和性能。

無名引用

對於一次性的,帶參數表達式,用LB可以節省不必要的class定義和維護,簡化程序的設計-維護代價。

比如下面的vector處理代碼,簡潔明了:
代碼:

vector<int> v1(10, 1);
int sum = 0;
for_each (v1.begin(), v1.end(), [&](int i){ sum += i; });//Line1


否則,我們必須定義一個function類,把如此簡單的事情復雜化。用了LB,我們把定義function 類的工作,轉交給編譯。VC++中,上述LB編譯的實現是產生一個隱身類:
代碼:

class  _lambda_a01 {
int &capture1_;
public:
_lambda_a01(int &x): capture1_(x) {}  //Line2
operator void (int i) { capture1_ += I; }
};


在引用時(Line1),它變成:
代碼:

_lambda_a01 lbd1(sum);
for(auto a:v1){
ldb1(a);
}

讀者也許好奇,為什麼C++不直接把LB轉換成inline expression (inline 表達式),而是要生成一個隱身類呢?這是因為LB的確可以當成“type”變量來用,這樣使得LB和其他類有了同等地位。比如:
代碼:

vector<int> v1(10, 1);
int sum = 0;
for_each (v1.begin(), v1.end(), [&](int i){ sum += i; });//Line1
vector<int> v2(10, 1);
int sum2 = 0;
for_each (v1.begin(), v1.end(), [&](int i){ sum2 += i; });//Line2

我們如果用上述的方法,Line1和Line2重復代碼,是軟件工程的大忌。我們可以用下列LB使用模式:

有名無型引用
代碼:

vector<int> v1(10, 1);
vector<int> v2(10, 1);
int sum = 0;
auto lb = [&](int i){ sum += i; };  //Line0
 
for_each (v1.begin(), v1.end(), lb);//Line1
sum = 0;                              // Line1.1
for_each (v1.begin(), v1.end(), lb});//Line2

在Line0,我們定義了一個有名(lb)無型的LB,可以在Line1和Line2重復使用。

注意的是,

1) 每個LB的“定義”都會產生新的“隱身”類,所以盡量用“有名引用”,會減少代碼的size,縮小工作集。

2) 定義時,LB一次性“俘獲”環境變量,所以上面修改後的代碼加了Line1.1,以便正確表達應用邏輯。

3) 俘獲可以是“傳值(by value)”也可以是“傳引用(by reference)。我們Line0用的是by reference.

有名有型引用

上面兩種LB使用模式,是LB應用的主要模式,它直接反映出了LB的優點。另一方面說,既然LB無非是隱身類,我們沒有理由不能把它當作普通變量使用。這個模式是一種簡化的functor使用模式。我們可以把LB定義成一個std::function,比如上面的auto lb可以定義成:
代碼:

std::function <void(int)> lb; //lb is a function which takes an integer and returns void

注意到用這個定義,使得我們可以推遲給LB變量賦值,甚至一變量賦多址(不同時間)。下面就是一個簡單用例:
代碼:

struct MyLambda
{
std::function <int (int)> _lbda;//line1
int _extra;
};
 
MyLambda TestLambdaObj(int t)
{
MyLambda ret;
if (t == 1)
{
ret._extra = t;
ret._lbda = [=](int x)  -> int { return t + x; }; //line2
return ret;
}
else
{
ret._extra = t;
ret._lbda = [=](int x)  -> int { return t * x; };//line3
return ret;
}
}
 
void TestLambdaFun2(int t)
{
MyLambda ret = TestLambdaObj(t);
int v = ret._lbda(t);                                //line4
printf(“v is ‘%d’ for type %d”, v, t);
}

我們先定義MyLambda數據類,並與其定義了一了function成員_lbda,根據C++ SPEC,他可以由LB轉換構造,並且和普通的類變量無甚區別。然後我們可以運行時給它賦值(line2,line3), 當作普通function來使用(line4)。

注意的是:

function的定義中沒有“閉包”的概念,閉包的形成是在LB創建時實現(line2,line3)。
把LB賦值給function變量,必然造成調用時(line4)的間接性(通過函數指針),其性能相當於虛擬函數,也不能inline化,當然比直接調用有所下降。
閉包(closure)是LB的獨特附加值

如果你問為什用LB而不用std::function?我的回答是“閉包”。

C++用LB來實現閉包,是一個簡化繁瑣的class初始化的syntax sugar。這一點是std::function所不可替代的。比如說:
代碼:

auto sum = 0;
auto step = 2;
auto lb = [&](int i){ sum += i + step; }//capture sum and step by ref

lb形成自己的閉包,自動從環境中俘獲了sum和step,若用class實現,上面的程序起碼增加10行代碼。
 
花籃
分享
_________________
There is no wisdom tree; nor a stand of a mirror bright, Since all is void, where can the dust alight?
樓主 | 電梯直達
閱讀會員資料 發送站內短信 主題 User photo gallery 禮物  
webdriver
(只看此人)




文章 時間: 2014-10-20 17:17 引用回復
LB性能初探

下面的簡單程序,測試四種功能完全一樣,但使用不同表達式的邏輯:

1)t =1 時用LB,

2)t=2 時用直接表達式

3)t=3 時用函數

4)t=4時用std::function間接調用LB
代碼:

void TestLambdaFun(int t)
{
using namespace std;
vector<int> v1(10, 1);
int x = 0;
int u = 0;
if (t == 1)
{
clock_t begin = clock();
for (int i = 0; i < 100000; ++i)
{
for_each (v1.begin(),
v1.end(),
[&x, &u](int i){ u += i+(x++); });// Line 1
}
clock_t end = clock();
auto spent = double(end – begin) / CLOCKS_PER_SEC;
printf(“spent for type ‘%d’ is %f u is %d\n”, t, spent, u);
}
else if (t == 2)
{
clock_t begin = clock();
for (int i = 0; i < 100000; ++i)
{
auto _First = v1.begin();
auto _Last = v1.end();
for (; _First != _Last; ++_First)
{
u = *_First+(x++);                  // Line 2
}
}
clock_t end = clock();
auto spent = double(end – begin) / CLOCKS_PER_SEC;
printf(“spent for type ‘%d’ is %f u is %d\n”, t, spent, u);
}
else if (t == 3)
{
clock_t begin = clock();
for (int i = 0; i < 100000; ++i)
{
auto _First = v1.begin();
auto _Last = v1.end();
for (; _First != _Last; ++_First)
{
FuncAdd(u, x, *_First);             // Line 3
}
}
clock_t end = clock();
auto spent = double(end – begin) / CLOCKS_PER_SEC;
printf(“spent for type ‘%d’ is %f u is %d\n”, t, spent, u);
}
else if (t == 4)
{
clock_t begin = clock();
std::function <void (int)> lbda;
for (int i = 0; i < 100000; ++i)
{
lbda = [&](int i){ u += i + (x++); };
for_each (v1.begin(), v1.end(), lbda); // Line 4
}
clock_t end = clock();
auto spent = double(end – begin) / CLOCKS_PER_SEC;
printf(“spent for type ‘%d’ is %f u is %d\n”, t, spent, u);
}
 
}
 
void FuncAdd(int &u, int &x, int i)
{
u = i+(x++);
}


下面是VC++ 2010中的測試結果:

在debug模式下,t=2時速度最快,這是因為t=1,t=3,t=4時都是用了函數調用,性能當然不及inline表達式。
在release模式下(選擇/Ob1優化,對inline函數進行inline擴展)
t=1和t=2速度完全一樣,比t=3時平均快3倍。當然,我們也可以把FuncAdd inline化。這裡的主要目的,是證明優化後,LB的性能和表達式完全一樣。證明C++ Lambda expression不是浪得虛名的隱身類的syntax sugar,而是名副其實的“表達式”。
t=4最慢,它和t=3類似。但是由於通過了std::function的虛擬函數表間接調用,/Ob1優化失去作用,使它不但要調用一個() operator,而且是通過“虛擬表”間接調用。所以從性能上說,把LB通過std::function間接使用,失去了LB的性能優勢。

總結

C++ 11 的lambda expression(簡稱LB),在可以保證和inline expression同樣性能的條件下,增加了參數功能和閉包功能,是我們寫出簡潔,明了,易維護代碼的絕佳工具。應用時,為了避免代碼重復和增加隱身類的數量,可用有名無型的LB變量。LB也可以賦值於std::function,當作函數指針使用,但是性能不及簡單地inline使用。
 
花籃
分享
_________________
There is no wisdom tree; nor a stand of a mirror bright, Since all is void, where can the dust alight?
沙發 | 返回頂端
閱讀會員資料 發送站內短信 主題 User photo gallery 禮物  
 
回復主題     |##| -> |=|     論壇首頁 -> IT人生 所有的時間均為 美國太平洋時間
1頁,共1


注:
  • 以上論壇所有發言僅代表發帖者個人觀點, 並不代表本站觀點或立場, 加西網對此不負任何責任。
  • 投資理財及買房賣房版面的帖子不構成投資建議。投資有風險,責任請自負
  • 對二手買賣中的虛假信息,買賣中的糾紛等均與本站無關。
  • 黃頁熱門商家 免費個人廣告
    發布商業廣告

    不能在本論壇發表新主題
    不能在本論壇回復主題
    不能在本論壇編輯自己的文章
    不能在本論壇刪除自己的文章
    不能在本論壇發表投票
    不能在這個論壇添加附件
    可以在這個論壇下載文件

    論壇轉跳: 

    webdriver, webdriver
    潛力帖子 精華帖子 熱門帖子
    法國情報高級官員證實至少一架陣風...
    巴印空戰0比6之啟示
    加拿大就業市場幾十年來最差 年輕人...
    戰機是陣風還是大疆?
    皇家鑄幣廠【渥太華開放日】
    趕緊加油!本周大溫油價就要起飛
    離譜 大溫超800張選票就這樣被忘了
    西洋老歌。五百二十三
    最是一年春好處:總結經驗,吸取教...
    遙遙領先 - 天朝鉈中毒已經如此普遍...
    2025年“五一”假期文化和
    今天看眼醫
    元初的參雞湯
    超級店的苞米
    日本的
    5月2日換幣盛況
    維達大師,另類收藏,請您欣賞!
    清代福州台伏鈔票
    四川官錢局鈔票
    大漢四川軍政府軍用銀票
    今年新幣發行計劃
    要出一個新的一元
    古董金幣
    mint三月新幣(四月新幣從22樓起,五...
    1999 mule 25分
    2025 蛇年敲幣活動
    加拿大新總理馬克卡尼
    我在小紅書被罵窮得沒錢給孩子買衣服
    美國2025年AWQ(美國婦女25c)發行計劃
    韓國空難FDR黑匣子缺失最後四分鍾關...
    皮爾今天在溫哥華 - 藍色wave - 保...
    幾分鍾前,中國強硬反擊,征34+50,...
    曼谷高樓直接倒了
    我說我希望特朗普贏,老公氣得眼睛...
    知乎?加西網上為什麼有老男人喜歡...
    明明有能力統台,大陸為何遲遲不動手?
    貌似ndp稍占上風。。。。。
    今天是感恩節,跟大家道個別,以後...
    咱最後還是投了ndp
    生平第一次被偷車了
    中國會不會武統台灣
    突發:台灣隊戰勝中國隊奧運奪冠,...
    溫哥華房姐出事了
    有在看總統辯論的嗎?
    退休幾年後的感悟

    最新新聞 熱門新聞 熱評新聞
    無人機穿越大理千年古塔落券洞內 涉事"飛手"被拘
    澤連斯基稱烏克蘭已准備好實現為期30天的停火!
    妻子舉報丈夫涉嫌重婚:同一小區內兩個"家"
    A股"掌門"薪酬曝光:13名董事長年薪超千萬
    美英宣布達成貿易協議 但具體細節尚待敲定
    緬甸多個電詐園區用"星鏈"上網 馬斯克被質疑...
    中國工信部出手整頓隱藏式汽車車門把手
    英媒:比黃金還珍貴的月塵從中國運抵英國
    美國官員:巴基斯坦用殲-10擊落印度陣風,沒用F-16
    紀念蘇聯偉大衛國戰爭勝利80周年,紀念的是什麼?
    應對貿易戰,歐盟的"籌碼"與"祭品"...
    反抗中共威權教會我的事:順從無法換來仁慈
    喉嚨出現5症狀 可能是食道癌前兆
    金巧巧回應"不適合演農村人"言論:原意是說演技窄
    印巴沖突升級以來莫迪首次發表講話,敦促各部...
    "疫苗導致的死亡海嘯已經來臨" 中國博主發文
    塵埃落定!"安胖"牽手桑巴軍團,劍指世界杯
    廣東發布31條振興消費方案 以舊換新、薪資成長…
    下狠手!9場狂丟16球 國足門神被棄用?
    歐冠決賽:法甲豪門被看高,藍黑軍團存隱憂
    61歲韋唯定居泰國,養水牛種水稻
    素裡雙重凶殺案 21歲男子被控罪
    科學家"算"出地球生命終結的時間
    高速路上2歲娃駕車 父親一臉淡定 網友憤怒
    上海推動商戶「輕微免罰」 讓企業休養生息振經濟
    中國很難介入"巴鐵"和印度之戰(圖
    川普稱中國要求會談 美財長:中國不是發展中國家
    "他們滿腦子都是錢,留學生千萬別來!"
    瑞士談判之際,美中傳來利好大消息
    中國不賣了 價漲210% "卡脖子"大殺器
    "疫苗導致的死亡海嘯已經來臨" 中國博主發文
    加拿大皇家馬戲團素裡列治文開演
    蓋茨擬捐幾乎全部身家 斥馬斯克殺最貧窮兒童
    溫市中心將聳立315米高樓 BC最高
    少女濾鏡徹底碎了!75歲王薇薇紅毯生圖嚇到網民
    內幕:習誤判慘遭重擊 終給川普遞上誠意清單
    塵埃落定!"安胖"牽手桑巴軍團,劍指世界杯
    廣東發布31條振興消費方案 以舊換新、薪資成長…
    瑞士談判之際,美中傳來利好大消息
    下狠手!9場狂丟16球 國足門神被棄用?
    歐冠決賽:法甲豪門被看高,藍黑軍團存隱憂
    61歲韋唯定居泰國,養水牛種水稻
    素裡雙重凶殺案 21歲男子被控罪
    上海推動商戶「輕微免罰」 讓企業休養生息振經濟
    中國很難介入"巴鐵"和印度之戰(圖

    更多方式閱讀論壇:

    Android: 加西網
    [下載]

    Android: 溫哥華論壇
    [下載]

    PDA版本: 論壇

    加西網微信

    加西網微博


    Powered by phpBB 2.0.8
    Terms & Conditions    Privacy Policy    Political ADs    Activities Agreement    Contact Us    Sitemap    

    加西網為北美中文網傳媒集團旗下網站

    頁面生成: 0.0505 秒 and 5 DB Queries in 0.0011 秒