其实,最开始接触到lambda函数是在关于python匿名函数的教程中。后来在一些资料上也看到了关于C++中匿名函数的用法的相关讲解。那么,借着这次整理C++11新特征的机会,就对C++中的lambda函数进行一下归纳:
1. Lambda 函数与表达式
C++11 提供了对匿名函数的支持(即,没有函数名的函数),称为** Lambda 函数(也叫 Lambda 表达式)**。其作用主要在于,如果代码里面存在大量的小函数,而这些函数一般只被一两处调用,那么不妨将它们重构成Lambda表达式,也就是匿名函数。作用就是当你想用一个函数,但是又不想费神去命名一个函数。
Lambda 表达式本质上与函数声明非常类似,其通用表达形式——$[捕获区] (参数区)->返回类型 {代码区}:
- [捕获区],指定在可见域范围内lambda表达式代码内可见的参数,即(除了形参之外)它可以使用的变量列表。在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为:
- [],沒有定义任何变量,即不捕获外部的任何变量。使用未定义变量会引发错误。
- [x, &y],x以传值方式传入(默认),y以引用方式传入。
- [&],任何被使用到的外部变量都隐式地以引用方式加以引用。
- [=],任何被使用到的外部变量都隐式地以传值方式加以引用。
- [&, x],x显式地以传值方式加以引用。其余变量以引用方式加以引用。
- [=, &z],z显式地以引用方式加以引用。其余变量以传值方式加以引用。
- [this],以值的方式捕获 this 指针。
- (参数区),指定lambda表达式内部变量定义
- ->返回类型,是返回类型,如果 lambda 代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。如果没有 return 语句,则类似 void f(…) 函数。
- {代码区},是Lambda表达式主题结构。
例如:
//通用表达形式:[捕获区](参数区)->返回类型 {代码区};
int n = [] (int x, int y) { return x + y; }(5, 4); //n=9
P.s:Lambda函数通过“函数体”后面的‘()’传入参数,如上例中的(5,4)。
2. 使用场景
Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。就目前来看,Lambda函数最常用的使用场景在于:sort、for_each等自定义比较函数。
下面给出了一个非常具体且完整的Lambda表达式的使用样例,可帮助我们加深理解:
class CTest
{
public:
CTest() : m_nData(20) { NULL; }
void TestLambda()
{
vector<int> vctTemp;
vctTemp.push_back(1);
vctTemp.push_back(2);
// 无函数对象参数,输出:1 2
{
for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });
}
// 以值方式传递作用域内所有可见的局部变量(包括this),输出:11 12
{
int a = 10;
for_each(vctTemp.begin(), vctTemp.end(), [=](int v){ cout << v+a << endl; });
}
// 以引用方式传递作用域内所有可见的局部变量(包括this),输出:11 13 12
{
int a = 10;
for_each(vctTemp.begin(), vctTemp.end(), [&](int v)mutable{ cout << v+a << endl; a++; });
cout << a << endl;
}
// 以值方式传递局部变量a,输出:11 13 10
{
int a = 10;
for_each(vctTemp.begin(), vctTemp.end(), [a](int v)mutable{ cout << v+a << endl; a++; });
cout << a << endl;
}
// 以引用方式传递局部变量a,输出:11 13 12
{
int a = 10;
for_each(vctTemp.begin(), vctTemp.end(), [&a](int v){ cout << v+a << endl; a++; });
cout << a << endl;
}
// 传递this,输出:21 22
{
for_each(vctTemp.begin(), vctTemp.end(), [this](int v){ cout << v+m_nData << endl; });
}
// 除b按引用传递外,其他均按值传递,输出:11 12 17
{
int a = 10;
int b = 15;
for_each(vctTemp.begin(), vctTemp.end(), [=, &b](int v){ cout << v+a << endl; b++; });
cout << b << endl;
}
// 操作符重载函数参数按引用传递,输出:2 3
{
for_each(vctTemp.begin(), vctTemp.end(), [](int &v){ v++; });
for_each(vctTemp.begin(), vctTemp.end(), [](int v){ cout << v << endl; });
}
// 空的Lambda表达式
{
[](){}(); []{}();
}
}
private: int m_nData;
};