Articles

C++11 lambda表达式

C++0x引入的特性中,最吸引我的是lambda表达式。之前为了要用STL中的泛型算法,经常会不知不觉就写出来一堆小的仿函数,导致代码很分散,阅读起来也不太方便。现在有了lambda表达式,方便极了,谁用谁知道!

举个例子:

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

struct functor
{
    void operator ()(int n) {
        cout << n << " ";
    }
};

int main()
{
    vector<int> ints(5);
    generate( ints.begin(), ints.end(), rand );
    for_each( ints.begin(), ints.end(), functor() );

    return 0;
}

类似functor这样的小型类会充斥代码,改用lambda表达式后,代码可以得到简化。

for_each( ints.begin(), ints.end(),
    []( int n ) { cout << n << " "; } );

虽然lambda表达式被放到了main的空间里,但事实上,在lambda表达式内部是无法访问main空间中的变量的。因为编译器需要在另外一个地方实现这个lambda表达式,类似上面的functor。lambda表达式必须明确的说明自己要捕获哪些main中的变量,才能在函数体中使用。

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> ints(5);
    generate( ints.begin(), ints.end(), rand );

    int factor = 5;
    for_each( ints.begin(), ints.end(),
        [factor]( int n ) { cout << n * factor << " "; } );

    return 0;
}

如果main空间中有很多变量需要被lambda表达式访问怎么办?总不能把所有变量都放到[]捕获列表里面吧?这时,可以通过[=]捕获所有变量。

int factor = 5;
for_each( ints.begin(), ints.end(),
    [=]( int n ) { cout << n * factor << " "; } );

那lambda表达式是否可以有返回值呢?答案是肯定的。

int factor = 5;
transform( ints.begin(), ints.end(), ints.begin(),
    [factor]( int n ) { return n * factor; } );

并且,可以通过一个特殊的->符号,指定lambda表达式的返回类型。

int factor = 5;
vector<double> doubles(5);
transform( ints.begin(), ints.end(), doubles.begin(),
    [factor]( int n ) -> double { return 1.0 * n * factor; } );

最后一个问题,如果lambda表达式需要修改main空间中的变量怎么办?可以通过将lambda表达式声明为mutable来解决。

int result = 0;
for_each( ints.begin(), ints.end(),
    [&result]( int n ) mutable { result += n; } );