可调用对象
- 函数
- 函数指针
- 函数类
- lamda表达式
- bind对象
函数类
重载了函数调用运算符()的类的对象,称为函数对象。
class callable
{
public:
void operator() (int x) const
{
cout << "callable::operator(): " << x << endl;
}
};
int main(){
callable c;
c(0);
}
相对于普通函数,函数类可以保存状态,有自己的类型。
lambda表达式
capture mutable exception attribute -> ret
- capture: 捕获列表,声明外部变量
- params: 形参列表,可以省略无参数
- mutable: 是否可以修改捕获的变量,可以省略捕获列表不能修改
- exception: 异常设定
- attribute: 属性
- ret: 返回值类型,可以省略,根据body的return推断
- body: 函数体
捕获
值捕获
被捕获的变量的值在lambda表达式创建时拷贝,不会受到外部变量的影响,同样,lambda表达式的修改也不会影响外部变量。
int main()
{
int a = 0;
auto f1 = [a] () { cout << a << endl; }; // 值捕获
auto f2 = [&a] () { cout << a << endl; }; // 引用捕获
auto f3 = [=] () { cout << a << endl; }; // 值捕获
auto f4 = [&] () { cout << a << endl; }; // 引用捕获
a++;
f1();
f2();
f3();
f4();
}
/*
0
1
0
1
*/
引用捕获
捕获的变量就是引用绑定的对象。
隐式捕获
不指定捕获列表,编译器会根据使用的外部变量自动推断捕获方式。
- [=] 按值捕获
- [&] 按引用捕获
混合方式
[=, &x] 按值捕获除x外的所有变量,x按引用捕获
[&, x] 按引用捕获除x外的所有变量,x按值捕获
mutable
按值传递时,默认情况下,lambda表达式不能修改捕获的变量,加上mutable关键字后,可以修改捕获的变量,但仍不影响外部变量。
形参
不支持默认参数,不支持可变参数
bind对象
bind可以绑定一个可调用对象和一组参数,返回一个新的可调用对象。
auto newCallable = bind(callable, arg_list);
arglist是参数列表,可以是占位符,也可以是具体的值。占位符_i表示newCallable的第i个参数。
预先绑定的参数通过值传递,占位符参数通过引用传递。
bind绑定类成员函数时,参数依次为成员函数指针(显式使用&,编译器对于成员函数不会自动转换),对象指针,成员函数参数。
std::function
模板类,抽象了函数参数和返回值,以上介绍的所有具有相同参数和返回值的函数对象都可以用同一类std::function表示,从而使用统一的处理方式。
一个例外时不能容纳类成员函数,因为类成员函数有一个隐藏的this指针。
可以推迟函数的执行,经常用于回调函数。