与将值作为参数的正常函数相比,函子有什么区别

时间:2013-04-15 12:21:13

标签: c++ c++11 functor

我是这个概念的新手,但是当我搜索差异和仿函数的好处时,他们能够在内部存储值并从构造中初始化这些值,但是正常的函数也以相同的方式工作,除非他们采取所有在函数调用中作为整体的参数。很可能我在某种程度上是错的,但是与正常函数相关的函子和技巧的好处在哪里

2 个答案:

答案 0 :(得分:3)

核心区别在于仿函数定义的类型不是函数。即使是无状态仿函数(没有任何附加数据)也可以利用这一点。例如,考虑在排序算法中使用std::less

template <typename Iterator, typename Comparator>
sort(Iterator begin, Iterator end, Comparator c) {
...
   if (c(*begin,*end)) { ...
...
}

被称为sort(v.begin(), v.end(), std::less<int>());。调用该函数时,会创建std::less<int>的实例并将其传递给模板。因为它是无国籍的,所以通过该功能的成本几乎为零。在函数内部,调用c(a,b)被确定为对c.operator()(a,b)的调用,并且编译器知道类型。它可以有效地内联调用(在这种情况下足够简单)并用单个比较指令替换它。

另一方面,等效的C函数qsort采用函数指针(不能通过值传递函数)。在qsort内部,编译器不知道所调用的函数是什么,并且它不能内联它,因此它必须为每次比较执行函数调用。

Functors既可以添加以后可以在调用地点使用的额外信息(使用普通函数也是不可能的),并传递额外信息,例如提供需要调用的信息(相同的行为可以是获得,但受到性能影响)或其他附加信息(类型可以有嵌套类型/ typedef,特征检查信息......)

答案 1 :(得分:1)

普通函数,独立或成员,只有在调用函数时才会传递的参数。因此无法将额外数据传递给函数。

这与仿函数不同。仿函数是对象的一个​​实例,因此可以存储传递给构造函数的数据(在传递仿函数时使用)。

使用C ++ 11时,事情会变得混乱,因为lambda还可以通过使用捕获来“存储”(技术上不正确的单词)值。或者使用std::bind,它允许您在实际调用可调用对象时将值绑定为参数。