lambda表达式即匿名函数。
1.下面看一个简单的lambda表达式的例子:(随机产生数组的值,然后输出)
int main(){
const int SIZE = 20;
int array[SIZE];
generate_n (array, SIZE,
[] () { return rand() % 30 + 1; });
for_each (array, array + SIZE,
[] (int a){ cout << a << " "; });
return 0;
}
2.lambda的构成
- lambda-introducer (捕获字段)
- lambda-parameter-declaration-list (变量列表)
- mutable-specification (捕获的变量可否修改)
- exception-specification (异常设定)
- lambda-return-type-clause (返回类型)
- compound-statement (函数体)
外部变量的捕获规则
默认情况下,即捕获字段为 [] 时,lambda表达式是不能访问任何外部变量的,即表达式的函数体内无法访问当前作用域下的变量。
如果要设定表达式能够访问外部变量,可以在 [] 内写入 & 或者 = 加上变量名,其中 & 表示按引用访问,= 表示按值访问,变量之间用逗号分隔,比如 [=factor, &total] 表示按值访问变量 factor,而按引用访问 total。
- [] 不截取任何变量
- [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
- [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
- [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
- [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
- [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
参数列表
lambda表达式的参数列表基本和函数的一致,不过有如下限制:
- 参数列表不能有默认参数
- 不能是可变参数列表
- 所有的参数必须有个变量名
如果你不提供 mutable-specification, exception-specification, 以及 lambda-return-type-clause,参数列表是也可以省略的。如下面的表达式:
int main() { int x = 4; int y = 5; int z = [=] { return x + y; }(); }
能否修改捕获的变量
如果在参数列表后加上了 mutable,则表示表达式可以修改按值捕获的外部变量的拷贝。
异常设置
和函数一样,可以用 throw 来限定表达式能够抛出哪些异常。
返回类型
如果设置返回类型,你需要在类型名前面加上 ->。如果你只有一个返回语句的话,返回类型可以省略,编译器将会为你做出判断。
函数体
lambda表达式的函数体和普通函数大致相同。
Lambda函数和STL
- vector<int> v;
- v.push_back( 1 );
- v.push_back( 2 );
- //...
- for ( auto itr = v.begin(), end = v.end(); itr != end; itr++ )
- {
- cout << *itr;
- }
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
//...
for ( auto itr = v.begin(), end = v.end(); itr != end; itr++ )
{
cout << *itr;
}
现在有了lambda函数你就可以这么写
- vector<int> v;
- v.push_back( 1 );
- v.push_back( 2 );
- //...
- for_each( v.begin(), v.end(), [] (int val)
- {
- cout << val;
- } );
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
//...
for_each( v.begin(), v.end(), [] (int val)
{
cout << val;
} );
而且这么写了之后执行效率反而提高了。因为编译器有可能使用”循环展开“来加速执行过程