#函数对象
一个重载了括号运算符()的类就是一个函数类。当该类的对象调用()运算符的时候,表现形式就像是函数一样,因此取名函数对象。
|
|
#对比普通函数的优势
-
函数对象有自己的状态,可以保存在类中,比如调用次数
CallCount:1 2 3 4 5 6int main() { Function f; for (int i = 0; i < 5; ++i) f(i); return 0; }输出结果:

-
函数对象有自己的类型,类型就是对应的类,而普通函数是没有的。使用这个类型可以用来传参,挂钩子,为STL库的函数的钩子提供自己的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23class Compare { public: bool operator()(const pair<int, int> &a, const pair<int, int> &b) { return a.second < b.second; /* 根据第二个元素构建大根堆 */ } }; int main() { /* 传入函数类型,挂钩子 */ priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> heap; heap.emplace(5, 18); heap.emplace(514, 123); heap.emplace(40, 11); heap.emplace(51, 21); heap.emplace(53, 91); heap.emplace(4, 146); while (!heap.empty()) { auto &ele = heap.top(); cout << "1: " << ele.first << " 2: " << ele.second << endl; heap.pop(); } return 0; }输出结果:

-
operator()直接定义在类内部,默认是内联函数,编译器会决定是否内联。
#Lambda
就是一个匿名函数对象,会有对应的匿名类。
|
|
返回类型编译器可以自己推导,可以不加。
捕获操作就像是在匿名类中添加成员变量,可以用来保存状态:
|
|
Lambda可调用括号运算符,有变量保存状态,因此就是等价一个匿名的函数类,编译的时候编译器为其实现一个类:
|
|
#值捕获
值捕获是默认状态,也可以用=显式表示。值捕获时如果要对捕获的变量进行修改,必须加上mutable关键字。
mutable关键字的作用是把值捕获进来的变量变成左值:

#引用捕获
修改捕获的变量同时会对外部变量进行修改。
|
|
#混合捕获
|
|