lambda表达式
C++11中引入了lambda表达式,用于定义匿名函数,使得代码执行更加灵活,方便了程序编写。一个lambda表达式表示一个可调用的代码单元,可将其理解为未命名的内联函数。与普通函数类似,lambda表达式也有参数表、返回值类型和函数体,但不同的是,lambda表达式可以定义在函数内部。lambda表达式的语法形式如下所示:
[捕获列表] (参数列表)->返回值类型 { 函数体 }
其中的“捕获列表”是由lambda表达式所在函数的局部变量构成的列表,通过捕获列表,lambda表达式可以使用所在函数的变量,捕获列表也可以为空。“参数列表”、“返回值类型”和“函数体”与普通函数中对应内容的含义相同。
下述代码在func()函数中定义了一个简单的lambda表达式,代码如下所示:
void func()
{
int n = 5; //func()函数的局部变量n
//定义lambda表达式,捕获列表说明表达式中将使用函数中的变量n
//表达式的参数为int x,表达式的返回值类型为bool,表达式实现了x和n的比较
auto f = [n](int x)->bool { return x > n; };
//通过f调用lambda表达式,传入实参值6,将完成6 > 5的比较,结果为true(1)
cout << f(6) << endl;
}
上述代码中,在func()函数中定义了lambda表达式:[n](int x)->bool { return x > n; }, 表达式完成了参数x和func()函数局部变量n的比较,结果为bool值。变量f接收了lambda表示式,对表达式的调用与普通函数的调用方法相同,都是使用调用运算符“()”,如f(6)。
根据实际情况,也可以省略参数列表和返回值类型,但必须保留捕获列表和函数体,若程序中存在下面的lambda表达式,程序运行正确,代码如下所示:
auto f = []{return 10;};
cout << f() << endl; //输出10
可以在容器中使用lambda表达式,简化程序编写。在func()函数中定义lambda表达式,操作vector容器,代码如下所示:
void func()
{
vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int value = 3;
//通过count_if()计算容器中满足条件的元素个数,条件由lambda表达式给出。
//本表达式中捕获列表为[=],表示可以使用本函数中所有局部变量的值
int cnt = count_if(vec.cbegin(), vec.cend(), [=](int n){return n > value; });
cout << "vector items : " << endl;
//调用for_each()依次显示容器中的元素
for_each(vec.begin(), vec.end(), [](int n){ cout << n << " "; });
cout << "\nFind " << cnt << " values > " << value << endl;
}
上述代码中使用了两个lambda表达式,第一个表达式出现在count_if()函数第三个参数位置上,描述了计算条件,通过count_if()将计算出容器中大于3的元素为6个。第二个lambda表达式出现在for_each()函数第三个参数位置上,实现对每个元素的输出。
上面几段代码中使用了捕获列表的几种形式,现将捕获列表的可用形式总结如下:
● []:空捕获列表,表示lambda表达式不使用所在函数的任何变量。
● [变量列表]:变量列表是用逗号分隔的lambda表达式所在函数的多个局部变量,默认情况下,捕获列表中所有变量均对函数局部变量进行拷贝,若变量名称前使用了&,则采用引用方式捕获。
● [&]:隐式捕获列表,表示采用引用方式使用lambda表达式所在函数的局部变量。
● [=]:隐式捕获列表,采用值捕获方式使用所在函数的局部变量。
● [&, 变量列表]:变量列表中包含0个或多个lambda表达式所在函数的变量,对这些变量将采用值捕获方式进行操作,函数中其他的变量将采用引用捕获方式进行操作。
● [=, 变量列表]:变量列表中包含0个或多个lambda表达式所在函数的变量,对这些变量将采用引用捕获方式进行操作,函数中其他的变量将采用值捕获方式进行操作。
下面给出一段代码说明引用捕获的用法,代码如下:
void func2()
{
vector<int> vec = { 1, 2, 3, 4, 5 };
int index = 0;
for_each(vec.begin(), vec.end(),
[&index](int n){ cout << "vec[" << (index++) << "]: " << n << endl; });
}
上述代码中使用了for_each()函数显示了容器中的每个元素及其下标,lambda表达式完成内容输出。在显示下标时使用了index变量,lambda表达式对index变量采用引用捕获方式,每显示一个元素index加1。