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函数体内可以直接改变该类中的变量,和类中的普通函数拥有一样的权限。
相关文章
暂无评论...