Lambdas
本文将介绍什么是Lambdas函数及如何使用Lambdas函数。
什么是Lambdas函数
Lambda函数是C ++中的一种匿名函数,主要用作C ++中的回调,它主要在我们必须创建非常小的函数以作为回调传递给另一个API时使用。
使用场景和示例
假设现在我有一个整数数组,我想遍历此数组并使用STL算法for_each打印所有元素。
首先让我们使用函数指针来做到这一点,
void display(int a){
std::cout << a << endl;
}
void demo0(){
vector<int> ary({ 1, 2, 3, 4, 5 });
for_each(ary.begin(), ary.end(), &display);
return;
}
在上面的示例中,为了进行简单显示,我们创建了一个单独的函数,从而造成了一定的开销。若要解决此问题,可以使用lambda函数。Lambda函数是一种匿名函数,它没有名称,但是您可以传递参数并从中返回结果。同样,其所有内容都将用作内联代码。
lambda函数的示例:
[](int i){
cout << i << endl;
}
以上示例中,
- []用于传递外部作用域元素
- (int i)用于传递参数x
将demo0() 升级为lambda函数的示例:
void demo1(){
vector<int> ary({1,2,3,4,5});
for_each(ary.begin(), ary.end(), [](int i){
cout << i << endl;
});
return;
}
将外部的元素传进Lambda函数中
情况一:使用[=]
[=](int &x) {
//所有外部范围元素都是按值传递的
}
情况二:使用[&]
[&](int &x) {
//所有外部范围元素都是通过引用传递的
}
通过下面的示例,可以看出如何在lambda函数内部使用外部范围元素。
void demo2(){
vector<int> ary({ 1, 2, 3, 4, 5 });
int value = 0;
for_each(ary.begin(), ary.end(), [&](int i){
//可以修改value,因为对所有外部作用域元素都有写访问权限。
value += i;
});
cout << value << endl; //15
for_each(ary.begin(), ary.end(), [=](int i){
//不能修改value,因为所有外部作用域元素在这里都有只读访问权限。
cout << value << endl; //允许读
//value += i; //编译时错误
});
for_each(ary.begin(), ary.end(), [](int i){
//不能访问value,因为所有外部作用域元素在这里都不可见。
//cout << value << endl; //编译时错误
});
return;
}
捕获指定外部变量
一个简单的Lambda语法是
[Captured variables](paameters) { function code }
外部作用域的局部变量可以在Lambda内部以两种模式捕获,即值传递和引用。
-
按值捕获局部变量
要通过值捕获局部变量,可在捕获列表中指定它们的名称,即:
void demo3(){ int v1 = 0; string s1 = "0"; auto func = [v1, s1](){ cout << v1 << s1 << endl; // v1 = 1; //编译时错误 // s1 = "1"; //编译时错误 }; func(); return; }在lambda内部,可以访问但不能更改它们,因为它们是const。但是,我们也可以通过添加
mutable关键字来运行在在lambda表达式中修改。但是,它们的修改不会影响外部作用域变量的值,因为它们是按值捕获的。例如。void demo3(){ int v1 = 0; auto func = [v1]() mutable{ v1 = 1; }; func(); cout << v1 << endl; //0 return; } -
通过引用方式捕获局部变量
要通过引用捕获局部变量,可在捕获列表中以前缀&指定它们的名称。
void demo4(){ int v1 = 0; auto func = [&v1](){ v1 = 1; }; func(); cout << v1 << endl; //1 return; }现在,捕获列表中指定的变量将通过引用方式捕获到lambda中。在lambda内部,可以访问它们,还可以更改其值。同样,由于它们是通过引用捕获的,因此它们的修改将影响外部作用域变量的值。
-
混合方式捕获
按值捕获全部外部局部变量,但是counter以引用方式捕获
auto func = [=, &counter] () mutable {};
在类中使用Lambda函数
要在Lambda函数中捕获成员变量,需要以按值方式捕获this指针。在lambda函数中捕获this指针将自动在lambda中捕获该对象的所有成员变量。
class Demo{
int value;
public:
Demo(){
auto func = [this](){
this->value = 1000;
};
func();
cout << value << endl;
}
};
注意事项
如果在lambda中我们是按引用捕获局部变量,那么我们需要确保在访问或调用lambda函数时,所有按引用捕获的局部变量仍在范围内。
如果lambda将尝试访问或修改按引用捕获的局部变量,而该局部变量不再在范围内,即由于堆栈展开而被破坏,则可能会发生崩溃。例如:
function<void()> getCallBack(){
int counter = 10;
auto func = [&counter]() mutable {
cout << "Before modify: "<<counter << endl;
counter = 20;
cout << "After modify: "<<counter << endl;
};
return func;
}
void demo5(){
auto func = getCallBack();
func();
return;
}
输出结果:
Before modify: -858993460
After modify: 20
在这里,我们尝试访问由于堆栈展开而已被破坏的变量。

本文详细介绍了C++11中的Lambda函数,包括其定义、使用场景和示例。Lambda函数作为匿名函数,常用于回调,能简化代码并减少函数指针带来的开销。文章讨论了不同类型的捕获方式,如按值、按引用以及混合方式,并提醒了在使用Lambda时需要注意的范围问题。
688

被折叠的 条评论
为什么被折叠?



