淺析C++11新特征的Lambda表達式。本站提示廣大學習愛好者:(淺析C++11新特征的Lambda表達式)文章只能為提供參考,不一定能成為您想要的結果。以下是淺析C++11新特征的Lambda表達式正文
lambda簡介
熟習Python的法式員應當對lambda不生疏。簡略來講,lambda就是一個匿名的可挪用代碼塊。在C++11新尺度中,lambda具有以下格局:
[capture list] (parameter list) -> return type { function body }
可以看到,他有四個構成部門:
1.capture list: 捕捉列表
2.parameter list: 參數列表
3.return type: 前往類型
4.function body: 履行代碼
個中,參數列表和前往類型可以疏忽。
上面,詳細看幾個簡略的例子:
auto f1 = [] { return 1; }; auto f2 = [] () { return 2; }; cout<<f1()<<'\t'<<f2()<<endl;
捕捉列表
lambda中的捕捉列表既可以捕捉值,也能夠捕捉援用。
捕捉值:
int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17}; int border = 8; auto f3 = [border](const int &i){ if(i > border) cout<<i<<'\t'; }; for_each(begin(test_data), end(test_data), f3); cout<<endl;
捕捉援用:
auto f4 = [&border](const int &i){ if(i > border) cout<<i<<'\t'; }; border = 6; for_each(begin(test_data), end(test_data), f4); cout<<endl;
經由過程輸入可以看出,lambda中起感化的border是修正後的6,證明了捕捉切實其實是是援用。
須要留意的是,在捕捉援用時,須要包管當lambda被挪用時,此援用依然有用。
捕捉列表還可以采取隱式捕捉的方法,即讓編譯器經由過程lambda的履行代碼來斷定須要捕捉哪些部分變量。
隱式捕捉可以捕捉值、援用或許二者混雜:
char space = ' '; auto f5 = [=](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f6 = [&](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f7 = [&, space](const int &i){ if(i > border) cout<<i<<space; }; border = 0; for_each(begin(test_data), end(test_data), f5); cout<<endl; for_each(begin(test_data), end(test_data), f6); cout<<endl; for_each(begin(test_data), end(test_data), f7); cout<<endl;
這裡的f7應用的混雜情勢,可以讀作“除space捕捉值以外,其他變量均捕捉援用”。
可變lambda
當lambda須要在個中修正被值捕捉的變量的值時,須要給lambda加上mutable症結字。不然會有編譯毛病。
auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<<i<<space; space='\t';} }; for_each(begin(test_data), end(test_data), f8); cout<<endl; cout<<1<<space<<2<<endl;
從輸入中可以看出,space在lambda f8中的值,在第一次挪用以後,就被釀成了制表符Tab;然則在lambda以外,space依然是空格。
前往類型
lambda的前往類型采取尾置前往類型的方法。普通的:
1.lambda假如只包括return語句,則編譯器可以揣摸其前往類型,此時可以不顯示指定前往類型;
2.不然,編譯器假定lambda前往void,而前往void的函數弗成以反悔任何詳細值,這在年夜多半情形下是個抵觸,是以須要顯示指定前往類型。
然則,經由現實測試,今朝的g++編譯器更聰慧了:關於第2點,今朝只需編譯器可以從lambda函數體中揣摸出函數的前往類型,就不須要顯式指定前往類型,例如:
auto f9 = [](const int i){if(i % 3) return i * 3; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f9); border = 0; for_each(begin(test_data), end(test_data), f6); cout<<endl;
lambda代碼塊中有多個return語句,而且還有if/else語句,然則編譯器可以依據return語句揣摸出,其前往值應當是一個int類型,所以可以省略尾置前往類型。
然則,像上面這類情勢,因為編譯器在揣摸前往類型時發明了紛歧致,所以必需顯式的指定前往類型:
auto f10 = [](const int i) -> double {if(i % 5) return i * 5.0; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f10); for_each(begin(test_data), end(test_data), f6); cout<<endl;
總結
1.lambda表達式情勢: [capture list] (parameter list) -> return type { function body },
個中parameter list和return type可以省略。
2.捕捉列表可以捕捉值[val],
也能夠捕捉援用[&ref]。
3.捕捉列表還可以隱式捕捉部分變量,異樣有捕捉值[=]和捕捉援用[&]兩種方法,首次以外還可以混雜捕捉[&, val]
或許[=, &ref]
。
4.當lambda須要修正捕捉的值時,須要加上mutable症結字。
4.當lambda沒法主動揣摸出前往值類型時,須要經由過程尾置前往類型的方法顯示指定。
以上就是C++11新特征之Lambda表達式的全體內容,願望本文對年夜家進修C++有所贊助。