Lambda 運算式語法
本主題說明 lambda 運算式的語法。它提供的範例會示範 lambda 運算式和這些項目如何與範例相關聯的結構化的項目。
下列程式會使用 lambda 運算式有兩種 STL 演算法: generate_n和for_each。Lambda 運算式出現在呼叫generate_n函式會指派的項目vector的前兩個項目總計的物件。Lambda 運算式出現在呼叫for_each函式列印的項目相同的vector物件至主控台。
// lambda_structure.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
// Create a vector object with each element set to 1.
vector<int> v(elementCount, 1);
// These variables hold the previous two elements of the vector.
int x = 1;
int y = 1;
// Assign each element in the vector to the sum of the
// previous two elements.
generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
// Print the contents of the vector.
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
// Print the local variables x and y.
// The values of x and y hold their initial values because
// they are captured by value.
cout << x << " " << y << endl;
}
如需有關generate_n函式,請參閱generate_n。如需有關for_each函式,請參閱for_each。
下列章節說明的文法 lambda 運算式,以及每個項目如何關聯使用者先前的範例。
Lambda 運算式的文法
下列型式的定義顯示文法中,以 BNF 格式,lambda 運算式的:
lambda 運算式
: lambda introducer lambda 參數宣告opt複合陳述式
lambda introducer
: [lambda-captureopt]
lambda 擷取
: 擷取預設
| 擷取清單
|擷取預設,擷取清單
擷取預設
: &
| =
擷取清單
: 擷取
|擷取清單,擷取
擷取
: 識別項
|&識別項
| this
lambda 參數宣告
: (lambda 參數-宣告清單opt)可變動規格opt例外狀況規格opt lambda 復位型別子句opt
lambda 參數-宣告清單
: lambda 參數
|lambda 參數,lambda 參數-宣告清單
lambda 參數
: decl 規範 seq 功能宣告子
lambda 復位型別子句
: ->type-id
下節將說明文法中簡介的範例與關聯的方式。
Lambda 運算式的屬性
下圖會將文法對應的範例。
在圖例中的圖說文字如下所示:
lambda introducer (稱為擷取子句稍後在本主題中)
lambda 參數-宣告清單 (稱為 參數清單稍後在本主題中)
可變動規格 (稱為 可變動的規格稍後在本主題中)
例外狀況規格 (稱為 例外狀況規格稍後在本主題中)
lambda 復位型別子句 (稱為 傳回型別稍後在本主題中)
複合陳述式 (稱為 lambda 主體稍後在本主題中)
下列章節將描述更詳細的文法。
擷取子句
Lambda 運算式可以存取任何具有自動存放工期和封閉範圍中的可存取的變數。擷取子句指定 lambda 運算式的主體是否會傳值方式或傳址存取封閉範圍中的變數: 有連字號的變數 (&) 前置詞由參考,也不需要的變數&值,以存取 [前置詞。擷取子句中, [],表示 lambda 運算式的主體存取封閉範圍中的任何變數。
預設擷取模式指定未明確指定的擷取變數是否會被擷取傳值方式或傳址。您可以指定預設抓圖模式 (capture-default在語法中) 藉由指定&或=為擷取子句的第一個項目。&項目會指定 lambda 運算式的主體存取所有擷取的變數傳除非您明確指定,否則。=項目會指定 lambda 運算式的主體存取所有擷取的變數的值,除非您明確指定,否則。比方說,如果 lambda 運算式的主體存取外部變數total的參考和外部變數factor的值,然後以下擷取子句是相同的:
[&total, factor]
[&, factor]
[=, &total]
您可以使用在類別方法的主體中使用 lambda 運算式。傳遞this擷取子句來提供存取給封入類別的方法和資料成員的指標。如需如何使用類別的方法使用 lambda 運算式的範例,請參閱範例: 使用 Lambda 運算式在主題中的方法Lambda 運算式的範例。
參數清單
Lambda 運算式的參數清單與類似的參數清單的函式,除了下列例外:
參數清單不能有預設引數。
參數清單不能有可變長度引數清單。
參數清單不能有未命名的參數。
Lambda 運算式可做為引數的另一個 lambda 運算式。如需詳細資訊,請參閱高階順序 Lambda 運算式主題中的Lambda 運算式的範例。
Lambda 運算式的參數清單是選擇性的。您可以省略的參數清單,如果您不要傳遞給 lambda 運算式引數,而不提供mutable-specification, exception-specification,以及lambda-return-type-clause項目。下列範例會顯示省略的參數清單的 lambda 運算式:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
可變動的規格
可變動的規格組件可讓您可以修改並擷取值的變數 lambda 運算式的主體。前述範例使用mutable關鍵字,使 lambda 運算式的主體可以修改它的外部變數的複本x和y,其中以傳值方式的 lambda 運算式會擷取。因為 lambda 運算式會擷取變數x和y的值,其值若要保持1呼叫之後generate_n。
例外狀況規格
您可以使用throw() ,表示該 lambda 運算式並不會擲回任何例外狀況的例外狀況規格。如同一般的函式,與 Visual C++ 編譯器會產生警告 C4297 若 lambda 運算式只宣告這throw()例外狀況規格和 lambda 主體擲回例外狀況,如下列範例所示:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
如需有關例外狀況規格的詳細資訊,請參閱例外狀況規格。
Return Type
Lambda 運算式的傳回型別部分就像一般的方法或函式的傳回型別部分。不過,傳回的型別後面的參數清單,且必須包含->傳回型別前。
如果 lambda 主體包含單一的 return 陳述式,或將 lambda 運算式並不會傳回值,您可以略過 lambda 運算式的傳回型別部分。如果 lambda 主體包含一個單一的 return 陳述式,編譯器會推論的傳回型別,傳回的運算式的型別。否則,編譯器會推論的傳回型別是void。
Lambda 運算式可能會產生另一個 lambda 運算式做為傳回值。如需詳細資訊,請參閱高階順序 Lambda 運算式主題中的Lambda 運算式的範例。
Lambda 主體
Lambda 主體的部分 lambda 運算式可以包含一般的方法或函式的主體可以包含任何項目。一般的函式和 lambda 運算式的主體可以存取下列類型的變數:
參數
在本機宣告變數
類別資料成員 (如果在類別內宣告)
任何了靜態存放裝置的實際工時 (比方說,全域變數) 的變數
此外,lambda 運算式可以存取它會擷取封閉範圍的變數。變數是明確地擷取到顯示該 lambda 運算式的擷取子句中。否則,此變數是隱含地擷取到。Lambda 運算式的主體所使用的預設抓圖模式會隱含地擷取到的存取變數。
lambda_parameter_list.cpp範例隱含會擷取區域變數x和y的值。下列範例包含 lambda 運算式,可明確地擷取變數n以傳值或隱含地擷取變數m由參考:
// captures_lambda_expression.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int m = 0, n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;
}
本範例會列印到主控台下列:
5
0
因為將變數n會擷取值,其值仍會保留0呼叫 lambda 運算式之後。
雖然 lambda 運算式只可以擷取有自動儲存的持續時間的變數,您可以使用 lambda 運算式的主體中的靜態存放裝置期間的變數。下列範例會使用generate函式,並將 lambda 運算式指派值給每個項目中vector物件。Lambda 運算式會修改用來產生下一個項目值的靜態變數。
// lambda_static_variable.cpp
// compile with: /c /EHsc
#include <vector>
#include <algorithm>
using namespace std;
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;
// The lambda expression that appears in the following call to
// the generate function modifies and uses the local static
// variable nextValue.
generate(v.begin(), v.end(), [] { return nextValue++; });
}
如需有關generate函式,請參閱generate。