我是这个概念的新手,但是当我搜索差异时,仿函数的好处是它们能够在内部存储值并从构造中初始化这些值,但是普通函数也以相同的方式工作,除了它们将所有参数作为一个整体在函数调用中。很可能我在某些方面是错误的,但函子与正常函数相关的技巧和好处在哪里
2 回答
核心区别在于函子定义的是类型而不是函数。即使是无状态函子(没有任何附加数据)也可以利用这一点。例如考虑使用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
,编译器不知道调用的函数是什么,也不能内联,所以每次比较都必须执行一次函数调用。
函子既可以添加额外的信息,以后可以在调用的地方使用(这对于普通函数来说是不可能的),也可以传递额外的信息,比如提供需要调用的信息(可以获得相同的行为,但是对性能有影响)或其他附加信息(类型可以有嵌套类型/类型定义,用于特征检查的信息......)
普通函数,独立的或成员的,只有它们的参数将在调用函数时传递。所以没有办法将额外的数据传递给函数。
这与函子不同。仿函数是对象的实例,因此确实可以存储传递给其构造函数的数据(在传递仿函数时使用)。
对于 C++11,事情有点混乱,因为 lambdas 还可以通过使用捕获来“存储”(技术上不正确的词)值。或者通过使用std::bind
which 允许您在实际调用可调用对象时将值绑定为参数。