函数对象

函数对象就是仿函数,之所以叫仿函数,是因为使用起来书写形式和调用函数的代码形式很像,之所以叫函数对象,是因为本shi质还是个对象,只不过写这个类是为了使用类似函数的功能。 仿函数就是重载了括号,例如以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
class myPrint{

public:
int cnt;
void operator()(int n) {

cout << n << endl;
++ cnt;
}
};

int main()
{

myPrint func;
func(2);
// myPrint()(2);
return 0;
}

myPrint类声明的对象就是函数对象,func()本质上是调用成员函数func.operator()(2),但是由于经过运算符重载后也可以写成func(2),形式就像是调用函数一样,所以称为函数对象 和普通的函数相比,有很多好处

  1. 可以在内部保存状态,例如这里cnt记录了函数调用次数
  2. 可以作为参数传递到其他函数(因为其内部有状态),类似函数指针

lambda表达式

形式如下 其中返回类型可写可不写,编译器可以自动推断

1
2
3
4
5
[捕获变量](形参)->返回类型 {

函数体内容
return 变量;
}

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
int main()
{

int m = 3, n = 4;
auto func = [&m](int &a, int &b) {

int temp = a;
a = b;
b = temp;
m = 10;
};
int a = 1, b = 2;
func(a, b);
cout << a << " " << b << " " << m << endl;
return 0;
}

捕获变量有几种形式

1
2
3
4
5
6
7
8
9
10
11
12
lambda表达式,从闭包作用域捕获变量而获得状态,分为传值和传引用。
捕获变量登记与函数对象中的示例数据成员。
[=] 值捕获所有变量
[&] 引用捕获所有变量
[&x] 引用捕获x变量
[x] 值捕获x
[=,&x] 默认值捕获,x变量通过引用捕获
[&,x] 默认引用捕获,x通过值捕获
[this] 捕获当前对象,可访问所有共有成员,C++20中不允许隐式捕获this
[=,x],[&,&x] 错误,重复指定
注意:即便默认要值捕获,全局变量总是使用引用捕获
使用初始化捕获表达式表达move捕获

值捕获的变量默认是const不可修改的,如果需要修改,则需要将lambda匿名函数对象用mutable修饰

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main()
{

int m = 3;
auto func = [m]() mutable{

m = 2;
};
return 0;
}