lambda是匿名函数,可以拿来当作inline函数使用(用于解决程序员的“起名困难综合症”)
lambda函数形式:
[...] (...) ... {...}
[] 内是一个capture,可以在lambda内部访问的"nonstatic外部变量",如果没有要访问的变量,可以为空。static变量是可以直接被访问的。
() 内是参数,和函数参数一样。
... 是mutable, 异常明细, 属性说明符(noexcept等), 或者返回类型。如果其中之一出现,那么必须出现()。
{} 内是函数体,在这里面写明lambda要完成的工作。
例如:
#include <iostream> using namespace std; int main() { []() { cout << "hello, world" << endl; }(); return 0; }
最后的一个()是函数调用。
也可以以如下方式调用:
auto f = []() { cout << "hello, world" << endl; }; f();
使用参数:
#include <iostream> using namespace std; int main() { auto f = [](int a) { cout << "hello, world " << a << endl; }; f(12); return 0; }
返回类型:
#include <iostream> using namespace std; int main() { auto f = [](int a) { cout << "hello, world " << a << endl; return a; }; auto k = f(12); cout << k << endl; return 0; }
C++的类型推导系统会自动推导出函数的返回类型,也可以写明:
// return int auto f = [](int a) -> int { cout << "hello, world " << a << endl; return a; }; // return double auto f = [](int a) -> double { cout << "hello, world " << a << endl; return a; };
Capture -- passing by value
#include <iostream> using namespace std; int main() { int xxx = 10; auto f = [xxx]() { cout << "hello, world " << xxx << endl; }; f(); return 0; }
将外部变量passing by value给lambda,lambda可以在内部访问xxx,但是不可以修改xxx。
Capture -- passing by reference
#include <iostream> using namespace std; int main() { int xxx = 10; auto f = [&xxx]() { cout << "hello, world " << ++xxx << endl; }; cout << xxx << endl; f(); cout << xxx << endl; return 0; }
lambda可以在内部修改xxx,并且会影响到外部变量。
特殊的形式:
[=] (...) ... {...} 将外部所有变量传递给lambda,但是不能在内部修改 -- passing by value
[&] (...) ... {...} 将外部所有变量传递给lambda, 可以在内部修改,并且影响外部变量 -- passing by ref..
[=,&y] (...) ... {...} 将所有变量传递给lambda,y可以在内部修改,其余变量不行
[y, &] (...) ... {...} 将所有变量传递给lambda,y不可以在内部修改,其余变量可以
mutable:
// from The C++ Standard Library #include <iostream> using namespace std; int main() { int id = 0; auto f = [id]() mutable { cout << "id: " << id << endl; ++id; }; id = 42; f(); f(); f(); cout << id << endl; return 0; } // 输出如下: // id: 0 // id: 1 // id: 2 // 42
在这段代码里由于有了mutable关键字,使得lambda变为了passing by value与passing by reference的混合体,在第一次调用时会制造一个临时的副本,之后的调用都会去修改这一个副本。值得注意的是:lambda从定义时捕获能够访问的值,此时id = 0,与f何时被调用无关。
不建议写出lambda的类型,如果非要写出类型,可以使用decltype(),或者使用STL内的function<>