轉載:http://blog.csdn.net/xuexiacm/article/details/39835085
lambda表達式:
- [capture_block](parameters) mutable exception_specification->return_type{ body }
lambda表達式包含以下部分:
捕捉塊(catpure block): 指定如何捕捉所在作用域中的變量,並供給lambda主體使用。
參數(parameter): (可選)lambda表達式使用的參數列表。只有在不使用任何參數,並且沒有自定mutable、一個exception_specification 和一個return_type的情況下可以忽略該列表,返回類型在某些情況下也是可以忽略的,詳見對return_type的說明:eg: [] {return 10;}
參數列表和普通函數的參數列表類似,區別如下:
參數不能有默認值。
不允許變長參數列表。
不允許未命名的參數。
mutable:(可選)如果所在作用域的變量是通過值捕捉到,那麼lambda表達式主體中可以使用這些變量的副本。這些副本默認標記爲const,因此lambda表達式的主體不能修改這些副本的值。如果lambda表達式標記爲mutable,那麼這些副本則不是const,因此主體可以修改這些本地副本。
exception_specification:(可選)用於指定lambda可以拋出的異常。
return_type:(可選)返回值的類型。如果忽略了return_type,那麼編譯器會根據以下原則判斷返回類型:
如果lambda表達式主體的形式爲{return expression;}那麼表達式return_type的類型爲expression的類型。
其他情況下的return_type爲void。
下面的例子演示瞭如何創建一個lambda表達式並立即執行這個表達式。這行代碼定義了一個沒有返回值也沒有任何參數的lambda表達式。
注意:尾部的(),這對括號使得這個lambda表達式立即執行:
- [] {cout << "Hello from Lambda" << endl; } ();
- string result = [](const string & str) -> string { return "Hello from " + str; }("second Lambda");
- cout << "Result: " << result << endl;
- Result: Hello from second Lambda
根據前面的描述,這個例子中的返回值可以忽略:
- string result = [](const string & str){ return "Hello from " + str; }("second Lambda");
還可以保存lambda表達式的指針,並且通過函數指針執行這個lambda表達式。使用C++11的auto關鍵字可以輕鬆地做到這一點:
- auto fn = [](const string& str) {return "hello from " + str; };
- cout << fn("call 1") << endl;
- cout << fn("call 2") << endl;
- Hello from call 1
- Hello from call 2
捕捉塊
lambda表達式的方括號部分稱爲lambda捕捉塊(capture block),在這裏可以指定如何從所在作用域中捕捉變量。捕捉變量的意思是可以在lambda表達式主體中使用這個變量。有兩種方式:
[=]:通過值捕捉所有變量
[&]:通過引用捕捉所有變量
指定空白的捕捉塊[]表示不從所在作用域中捕捉變量。還可以酌情決定捕捉那些變量以及這些變量的捕捉方法,方法是指定一個捕捉列表,其中帶有可選的默認捕捉選項。前綴爲&的變量通過引用捕捉。不帶前綴的變量通過值捕捉。默認捕捉應該是捕捉列表中的第一個元素,可以是=或&。
例如:
[&x]只通過引用捕捉x,不捕捉其他變量。
[x]只通過值捕捉x,不捕捉其他變量。
[=, &x, &y]默認通過值捕捉,變量x和y例外,這兩個變量通過引用捕捉。
[&, x]默認通過引用捕捉,變量x例外,這個變量通過引用捕捉。
[&x, &y]非法,因爲標誌符不允許重複。
通過引用捕捉變量的時候,一定保證黨lambda表達式在執行的時候,這個引用還是可用的。
將lambda表達式用作返回值
定義在<functional>頭文件中的std::function是多態的函數對象包裝,類似函數指針。它可以綁定至任何可以被調用的對象(仿函數、成員函數指針、函數指針和lambda表達式),只要參數和返回類型符合包裝的類型即可。返回一個double、接受兩個整數參數的函數包裝定義如下:
- function<double(int, int)> myWrapper;
- function<int(void)> multiplyBy2Lambda(int x)
- {
- return [=]()->int{return 2 * x; };
- }
在這個例子中,lambda表達式的返回類型和空參數列表可以忽略,可改寫爲:
- function<int(void)> multiplyBy2Lambda(int x)
- {
- return[=] {return 2 * x; };
- }
可以通過以下方式調用上述函數:
- function<int(void)> fn = mutiplyBy2Lambda(5);
- cout << fn() << endl;
- auto fn = mutiplyBy2Lambda(5);
- cout << fn() << endl;
mutiplyBy2Lambda()示例通過值捕捉了變量x:[=]。假設這個函數重寫爲通過引用捕捉變量:[&],如下所示。根據代碼所示。根據代碼後面的解釋,下面這段代碼不能正常工作:
- function<int(void)> mutiplyBy2Lambda(int x)
- {
- return[&] {return 2 * x; };
- }
lambda表達式通過引用捕捉變量x。然而,lambda表達式會在程序後面執行,而不會在mutiplyBy2Lambda()函數的作用域中執行,在那裏x的引用不再有效。
將lambda表達式用作參數:
您可以編寫lambda表達式作爲參數的函數。例如,可通過這種方式實現回調函數。下面的代碼實現了一個testCallback()函數,這個函數接受一個整數vector和一個回調函數作爲參數。這個實現迭代給定vector中的所有元素,並對每個元素調用回調函數,回調函數接受vector中每個元素作爲int參數,並返回一個布爾值。如果回調函數返回false,那麼停止迭代。
- void testCallback(const vector<int>& vec, const function<bool(int)>& callback)
- {
- for (auto i : vec)
- {
- if (!callback(i))
- break;
- cout << i << " ";
- }
- cout << endl;
- }
- vector<int> vec(10);
- int index = 0;
- generate(vec.begin(), vec.end(), [&index] {return ++index; });
- for each (vec.begin(), vec.end()m[](int i) {cout << u << " "; });
- {
- cout << endl;
- testCallback(vec, [](int i){return i < 6; });
- }
輸出結果:
- 1 2 3 4 5 6 7 8 9 10
- 1 2 3 4 5