1.可调用对象(callable object)类别包括:
函数
函数指针
重载了函数调用运算符的类
lambda 表达式
2.lambda表达式形式:
[capture list] (parameter list) -> return type { function body }
capture list (捕获列表)是一个 lambda 所在函数中定义的局部变量的列表(通常为空),空捕获列表表明此 lambda 不使用它所在的函数中的任何局部变量, return type、parameter list 和 function body 与任何普通函数一样,分别表示返回类型、函数列表和函数体,但是与普通函数不同,lambda 必须使用尾置返回来指定返回类型
尾置返回类型跟在形参列表后面并以一个 -> 符号开头,为了表示函数真正的返回类型跟在形参列表之后,在本应该出现返回类型的地方放置了一个auto
auto func(int i) -> int(*)[10]; // func接受一个 int 类型的实参,返回一个指针,该指针指向含有10个整数的数组
lambda 可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
auto f = [ ] { return 42; };
lambda 的调用方式与普通函数调用方式相同,都是使用调用运算符
cout << f() << endl;
lambda 中忽略括号和参数列表等价于指定一个空参数列表
lambda 中忽略返回类型,可根据函数体中的代码推断出返回类型
3.lambda 不能有默认参数
4.捕获列表
以一对 [ ] 开始,可以在其中提供一个以逗号分隔的名字列表,这些名字都是 lambda 它所在函数中定义的
捕获列表只用于局部非 static 变量, lambda 可以直接使用局部 static 变量和它所在函数之外声明的名字
与参数传递类似,变量的捕获方式也可以是值或引用
值捕获的前提是变量可以拷贝,与参数不同,被捕获的变量的值是在 lambda 创建时拷贝,而不是调用时拷贝
lambda 捕获的都是局部变量,以引用方式捕获的变量与其他任何类型的引用的行为类似,采用引用方式捕获一个变量,就必须确保被引用的对象在 lambda 执行时候时存在的
如果函数返回一个 lambda ,则与函数不能返回一个局部变量的引用类似,此 lambda 不能包含引用捕获
尽量减少捕获数据量,避免捕获指针或引用
隐式捕获: [ &, c] (const string &s) { os << s << c; } // os 是隐式捕获,引用捕获方式; c 是显式捕获,值捕获方式
混合使用隐式捕获和显式捕获时,捕获列表中第一个元素必须是一个 & 或 = ,显式捕获的变量必须使用与隐式捕获不同的方式
默认情况下,对于一个值拷贝的变量, lambda 不会改变其值,如果要改变一个被捕获变量的值,就必须在参数列表首加上关键字 mutable,就是 mutable 前面必须要有 ()
auto f = [v] ( ) mutable { return ++v;}
一个引用捕获的变量是否可修改历来与此引用指向的是一个 const 类型还是一个非 const 类型