undefined

一、仿函数

Functor/Function Object翻译过来就是仿函数,它是通过重载()运算符模拟函数行为的类。也就是说,它不是函数(所以仿函数翻译的很贴切)。因为它重载了()运算符,因此可以像调用函数一样对它进行调用。STL中大量运用了Function Object,也提供了很多预先定义的Function Object。还是从vector遍历举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PrintInt
{
public:
void operator()(int elem) const
{
std::cout<<elem<<' ';
}
};

std::vector<int> v;
for_each(v.begin(),v.end(), PrintInt());

//C++ 11 lambda stype
for_each(begin(v), end(v), [](int n){ cout<< n <<", "; });

仿函数的优点:

1.仿函数是对象,可以拥有成员函数和成员变量,即仿函数拥有状态(states)
2.每个仿函数都有自己的类型
3.仿函数通常比一般函数快(很多信息编译期确定)

二、闭包

闭包Closure)可以被理解为一个附带数据的操作,WikiPedia 对闭包的定义是 *”In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions.”*,其中有两层含义:

  1. 词法作用域(lexically scoped)的名字绑定(name binding):在词法作用域(C++ 的词法作用域是静态绑定的,包括块、函数、类、命名空间、全局作用域等)中,变量名与其词法上下文的标识符相关联,而独立于运行时的调用栈;
  2. 函数被当作头等公民(first-class citizen):在运行时可以构造一个函数对象并将其作为参数传递给其他函数;

显然 C++ 98 并不符合这两点定义,因此 C++ 98 中并没有严格意义上的闭包,但我们可以用仿函数(Functor)来模拟闭包的行为;仿函数即一个重载了小括号操作符的类,这个类拥有与函数相近的行为方式,它拥有自己的私有成员变量,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Adder
{
public:
int operator()(int num)
{
sum += num;
return sum;
}

Adder() : sum(0) {}
Adder(int num) : sum(num) {}
private:
int sum;
};

int main()
{
Adder adder(0);
cout << adder(1) << endl;
cout << adder(2) << endl;
cout << adder(3) << endl;
}

相比之下 golang 中真正的闭包显得简洁很多:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unc adder() func(int) int {
sum := 0
return func(num int) int {
sum += num
return sum
}
}

func main() {
numAdder := adder()
fmt.Println(numAdder(1))
fmt.Println(numAdder(2))
fmt.Println(numAdder(3))
}

三、匿名函数

C++ 11 标准中正式引入了匿名函数,也叫做 lambda 表达式(Lambda Expression);匿名函数是一种没有被绑定标识符的函数,可以用于很方便地定义一个临时的函数对象,或作为一个函数对象传递给更上层的函数(例如 std::for_each),其在 C++ 11 的语法上表现得非常轻量级,不需要像普通的具名函数一样单独在头文件中作出声明,且符合闭包的定义

1. 闭包和匿名函数的关系

  1. 匿名函数和闭包的关系就如同类和类对象的关系,匿名函数和类的定义都只存在于源码(代码段)中,而闭包和类对象则是在运行时占用内存空间的实体;
  2. 对匿名函数的定义会生成一个独一无二的类,并在运行时生成其类对象;
  3. 可以知道实际上匿名函数也是用仿函数实现的,它实际上是 C++ 11 加入的语法糖,不过其语法特性是符合闭包定义的。