lambda表達式也稱匿名函數,c++11新增內容。
語法如下:
/*
參數説明:
capture list: 捕獲列表,是一個lambda所在函數中定義的局部變量列表
parameter list: 參數列表
return type: 返回類型
function body: 函數體
*/
[capture list] (parameter list) -> return type {function body}
lambda表達式可以理解為可調用的代碼單元,
可以忽略參數列表和返回類型,但必須永遠包含捕獲列表和函數體
auto ret = []() {
return 5;
};
cout << ret() << endl;
值捕獲
值捕獲的前提是變量可以拷貝。變量的值是在lambda創建時拷貝,而不是調用時拷貝,因此其修改不會影響到lambda內部對應的值。
默認情況下:如果以傳值方式捕獲外部變量,則在Lambda表達式函數體中不能修改該外部變量的值。
當按值的方式獲取外部變量時,是無法更改獲取過來的值的,除非使用mutable關鍵字聲明,就可以更改(更改的不是外部變量原本地址裏的值,而是lambda函數體內的副本);
int main()
{
int num = 2;
auto ret = [num] () { return num; };
num += 2;
cout << ret() << endl; //輸出 2
cout << num << endl; //輸出 4
return 0;
}
引用捕獲
當按引用的方式捕獲外部變量時,lambda函數體內可以更改此值,更改的是外部變量原本地址裏的值;
int main()
{
int num = 2;
auto ret = [&num] () { return num; };
num += 2;
cout << ret() << endl; //輸出 4
cout << num << endl; //輸出 4
return 0;
}
隱式捕獲
隱式捕獲有兩種方式,分別是[=]和[&]。[=]表示以值捕獲的方式捕獲外部變量,[&]表示以引用捕獲的方式捕獲外部變量
當按值的方式獲取外部變量時,是無法更改獲取過來的值的,除非使用mutable關鍵字聲明,就可以更改(更改的不是外部變量原本地址裏的值,而是lambda函數體內的副本);
當按引用的方式捕獲外部變量時,lambda函數體內可以更改此值,更改的是外部變量原本地址裏的值;
int main()
{
int num = 2;
//可以捕獲外部變量
auto ret = [=] () {
return num;
};
//會報錯 ,無法修改外部變量
auto ret = [=]() {
return num++;
};
//可以捕獲外部變量
auto ret = [&]() {
return num;
};
//可以法修改外部變量
auto ret = [&]() {
return num++;
};
return 0;
}
混合方式捕獲
lambda還支持混合方式捕獲,即同時使用顯示捕獲和隱式捕獲。
混合捕獲時,捕獲列表中的第一個元素必須是 = 或 &,此符號指定了默認捕獲的方式是值捕獲或引用捕獲 。
需要注意的是:顯示捕獲的變量必須使用和默認捕獲不同的方式捕獲。
int main()
{
int a = 2;
int b = 3;
auto f1 = [=, &a]() { return a + b; }; //正確,默認值捕獲,顯示是引用捕獲
auto f2 = [=, a]() { return a + b; }; //編譯出錯,默認值捕獲,顯示值捕獲,衝突了
auto f3 = [&, a]() { return a + b; }; //正確,默認引用捕獲,顯示是引用捕獲
auto f4 = [&, &a]() { return a + b; }; //編譯出錯,默認引用捕獲,顯示引用捕獲,衝突了
return 0;
}
修改值捕獲的值
在Lambda表達式中,如果以傳值方式捕獲外部變量,則函數體中不能修改該外部變量,否則會引發編譯錯誤。
如果你希望被值捕獲的值被改變,就必須在參數列表首加上關鍵字mutable。
//語法
[capture list] (parameter list) mutable -> return type {function body}
int main()
{
int num = 2;
auto f1 = [num]()mutable { // 不會報錯
num++;
cout << num << endl;
};
auto f2 = [=]()mutable { // 不會報錯
num++;
cout << num << endl;
};
cout << num++ << endl;
f1();
f2();
return 0;
}
- 當按值的方式獲取外部變量時,是無法更改獲取過來的值的,除非使用mutable關鍵字聲明,就可以更改(更改的不是外部變量原本地址裏的值,而是lambda函數體內的副本);
- 當按引用的方式捕獲外部變量時,lambda函數體內可以更改此值,更改的是外部變量原本地址裏的值;
- 當在類中,lambda表達式捕獲this指針時,lambda函數體內可以直接改變該類中的變量,和類中的普通函數擁有一樣的權限。