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

首頁

新聞資訊

論壇

溫哥華地產

大溫餐館點評

溫哥華汽車

溫哥華教育

黃頁/二手

旅游
搜索:  

 論壇通告:  轉載新聞請務必注明出處,這些媒體請不要轉,謝謝   請不要上傳第三方有版權的照片,請尊重版權,謝謝   批評商家需要注意  
 個人空間: XY | 湖裡湖塗 | 客觀中立而實事求是,唯服理據而杜絕辱罵 | NotmeL8 | 忽然聽到一個墨西哥女仔唱。呐呐呐呐呐呢呐 | 白龍王許道長 | 我大爺 | 亂想 | 血流成河 | 顧曉軍 | 羅蓬特機器人 | 我的退休生活 | Amy Yi | 快樂的獅子 | 我在溫哥華 | 滄海一聲笑 | little fish in the sky | 一襲絳襦落鵬城,九天玄女下凡間。 | 真情Z下海 | xian
 最新求助: 請問誰知道哪裡有賣理發的電動推子?   忽然有個疑問:戰爭時期,加拿大拿PR卡未入籍的永久居民會被強制服兵役嗎?   這個銀條   如何修改會員名?
 論壇轉跳:
     發帖回帖獲取加西鎊, 兌換精彩禮物

論壇首頁 -> IT人生

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



回復主題  圖片幻燈展示  增添帖子到書簽中  給帖子中的發貼者批量贈送獻花或者花籃    |##| -> |=|        發表新主題
閱讀上一個主題 :: 閱讀下一個主題  
作者 正文
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
    潛力帖子 精華帖子 熱門帖子
    新資本利得稅刺激大批房源上市 爭相...
    一周麻辣點評:地產稅收就是搶錢
    現在國際事務,都是由G7來敲啊
    國民黨立委、老娘最大翁曉玲在今日...
    飽了也頭暈
    不再去美國購物了
    常凱申你特麼算老幾?
    加拿大政治體制
    周一樂一樂,中國抗日神劇
    溫東小兵,你大爺,心涼了!他不上當!
    這就是阿裡巴巴新“數學天才”? 被...
    哈哈馬
    奈飛上的紀錄片
    去吃韓國人開的日本餐
    面向足球球迷的 2024 年歐洲杯
    在首爾景福宮見到了明娘娘
    在Victoria華裔博物館裡面的一套token
    日本五日游記
    Mule Coin 無法抗拒的魅力之一:200...
    法國阿爾卑斯山區
    明天又要上班了
    漂亮的MS66
    The Value of Money
    再去chief peak
    這些是不是真貨?
    同號雷達鈔
    今天包粽子 兼和粉紅吵架
    熱烈恭賀錢幣小站新任版主四季豆同學
    北溫換硬幣活動取消
    加拿大唯一無國籍的硬幣
    你們洗一次牙的價格一般多少錢?
    最近愛上了KALE
    刺傷4美國講師 凶手身份曝光,順便...
    從64看中國人的奴性和殘暴。
    大溫2室租金將達2800
    在北美得了大病真是只能等死了
    國內最驕傲的兩件事外賣和快遞
    烏克蘭已經花掉了美國七百多億美元
    大家如何看待北京同仁堂汞超標5萬倍...
    身在海外,痛罵國內人不反抗挺壞的
    95個小時,這是看急診嗎
    疫情4年後,海外華人去中國的觀感
    在加做房東有罪嗎?
    坎昆比夏威夷好玩
    中國沒有恐襲

    最新新聞 熱門新聞 熱評新聞
    福建上杭山體滑坡一寺廟倒塌 村民:一家6口失聯
    冷藏車載8人窒息身亡背後:農閒打零工的大齡女工
    傳俄羅斯在中國大量采購一物資(圖
    走線非法移民激增,厄瓜多爾暫停對中國公民免簽
    "開使館車堵路叫囂女子"身份曝光 北京警方通報
    北京南海襲擊菲律賓船只 用意曝光
    美國會高調抗北京,貿易團體避風頭紛與中企切割
    醫保患者住院15天必須出院?兩部門:建議舉報
    北京大幅減持美債?高盛最新報告揭"玄機"
    普丁凌晨才抵達平壤,南韓媒體譏:遲到隊長不意外
    突發!上海地鐵發生持刀傷數人 嫌犯遭捕
    美國:加沙停火可以結束以色列與真主黨的沖突
    席琳·迪翁有望獻唱奧運開幕式?!驚喜現身首映禮
    中國南方暴雨引發洪災,至少九人死亡
    英偉達市值超越微軟,成為全球第一
    去加拿大開挖掘機:有落差,但更快樂
    經濟不好方丈也要跑路?傳出售寺廟
    律師賄賂法官之妻 僅判行政處罰
    BMW汽車使用被禁中國零件擴大調查
    被困國產電動車喊救命 理想車撞一排
    西捷維修師工會發72小時罷工通知
    盜竊轉賣室友奢侈品 華裔女生被捕
    禍不單行,中國出口電動車被他重錘
    加國槍案三人死亡 貸款經紀人身亡
    美5月零售不如預期 月增僅0.1%
    神秘深海烏賊育卵曝光 揭繁殖之謎
    薄熙來死黨 72歲正部級高官病亡
    戰爭初期烏克蘭曾願割地 換入歐盟
    打趴外國企業,打工人就幸福了嗎?
    殘酷的閒暇:女工冷藏車與和鄉村圖
    盜竊轉賣室友奢侈品 華裔女生被捕
    姜萍事件是徹頭徹尾的炒作,始作俑
    大溫巴士總站將拆除 剛翻新裝修完
    正見證一個洲際變遷 俄中帝國夢魘
    多花20萬買房短租 BC業主現在崩潰
    被困國產電動車喊救命 理想車撞一排
    貸款還款增加一倍多 加國夫婦震驚
    影響幾億人,養老金即將發生巨變
    加國"路怒"視頻瘋傳 男子持刀威脅
    BMW汽車使用被禁中國零件擴大調查
    西捷維修師工會發72小時罷工通知
    為俄押運黃金、與港府關系密切
    禍不單行,中國出口電動車被他重錘
    加國槍案三人死亡 貸款經紀人身亡
    美5月零售不如預期 月增僅0.1%

    更多方式閱讀論壇:

    Android: 加西網
    [下載]

    Android: 溫哥華論壇
    [下載]

    PDA版本: 論壇

    加西網微信

    加西網微博


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

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

    頁面生成: 0.0525 秒 and 7 DB Queries in 0.0017 秒