一:什么是闭包
闭包有很多定义,一种说法是:闭包是带有上下文的函数,说白了,就是有状态的函数,这其实就是一个类,换个名字而已。
一个函数,带上一个状态,就变成了闭包,那什么叫“带上状态”? 意思就是这个闭包有属于自己的变量,这些变量的值是创建闭包的时候设置的,并在调用闭包的时候,可以访问这些变量。
函数是代码,状态是一组变量,将代码和变量捆绑(bind),就形成了闭包。
二:闭包的实现
2.1:重载operator()
因为闭包是一个函数加一个状态,这个状态通过隐含的 this指针传入,所以闭包必然是一个函数对象,因为成员变量就是极好的保存状态的工具,因此实现 operator()运算符重载,该类对象就能作为闭包使用。默认传入的 this指针提供了 访问成员变量的 途径。
/**
闭包的使用
*/
#include<iostream>
#include<string>
using namespace std;
class MyFunctor
{
public:
// 通过列表的形式初始化成员变量
MyFunctor(int temp) :count(temp) {};
// 重载operator()操作符
int operator()(int temp) {
return temp + count;
}
public:
int count;
private:
};
int main() {
int count = 1;
// 调用构造函数给成员变量赋值
MyFunctor f(count);
cout << "result: " << f(1) << endl;
}
2.2:Lambda表达式
int main() {
int count = 1;
// lambda表达式
auto f_lambda = [=](int f)->int
{
return f + count;
};
cout << "f_lambda result: " << f_lambda(1) << endl;
}
点评: 通常 function<int(int)> f = [ ] (int x) {return x};
通常这个叫闭包。
闭包 [ ] 中可以添加 = 或者 & 两个运算符,查过 cpp reference后,这个叫 capture(捕获),即使用闭包外的变量方式。我们讨论下这两个运算符:
2.2.1:[=]() {} :这是对闭包外变量进行const 引用的形式,即不允许修改闭包外的变量 。
int main() {
int count = 1;
auto f_lambda1 = [=](int i)->int
{
count = 2; // error: 表达式必须是可修改的左值(因为capture捕获的是const引用形式)
return i + count;
};
}
2.2.2:[&] () {} : 这是对闭包外变量进行引用的形式,可以修改闭包外的变量,并且保留为修改后的值
int main() {
int count = 1;
auto f_lambda1 = [&](int i)->int
{
count = 2;
return i + count;
};
cout<< f_lambda1(2)<< endl;
}
// 打印结果:4
2.3:lambda表达式
标准库提供的bind是更加强大的语法糖,将手写需要很多代码的闭包,浓缩到一行 bind就可以搞定了
int func(int temp, int count) {
return temp + count;
}
int main() {
int count = 1;
// 调用构造函数给成员变量赋值
// MyFunctor f(count);
// cout << "result: " << f(1) << endl;
// lambda表达式
/*auto f_lambda = [=](int f)->int
{
return f + count;
};
cout << "f_lambda result: " << f_lambda(1) << endl;*/
// bind表达式
function<int(int)> f_bind = bind(func, placeholders::_1, count);
cout<< f_bind(3)<< endl;
}