我知道STL中使用的函数对象只是一个简单的对象,我们可以像操作一样操作它。我可以说功能和功能对象的工作是一样的。如果这是真的,那么为什么我们应该使用函数对象而不是函数?
答案 0 :(得分:6)
主要的好处是对函数对象(仿函数)的调用通常是可内联的,而对函数指针的调用通常不是(例如,将C的qsort
与C ++的std::sort
进行比较)。对于非平凡的对象/比较器,C ++应该杀死C的排序性能。
还有其他好处,例如,您可以在仿函数中绑定或存储状态,使用该函数不能执行原始函数。
修改强> 道歉没有直接参考,但Scott Meyers在某些情况下声称改善了670%: Performance of qsort vs std::sort?
编辑2 表演笔记的内容如下:
函数指针参数禁止内联的事实解释了一个问题 观察到长期的C程序员经常难以置信: C ++的排序实际上总是让C的qsort变得尴尬 速度。当然,C ++有实例化的函数和类模板 看起来很滑稽的operator()函数在C简单时调用 函数调用,但所有C ++“开销”都被吸收了 汇编。在运行时,sort对其比较进行内联调用 函数(假设比较函数已内联声明 并且它的主体在编译期间可用)而qsort调用它 比较函数通过指针。最终的结果就是排序 跑得快。在我对一百万双打矢量的测试中,它跑了 要快670%,但不要相信我的话,自己尝试一下。它的 在比较功能对象和实际功能时很容易验证 作为算法参数,有一个抽象奖金。
-Scott Meyers "Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library" - Item 46
答案 1 :(得分:2)
函数对象对函数的好处是它可以保存状态(来自wikipedia):
#include <iostream>
#include <iterator>
#include <algorithm>
class CountFrom {
private:
int &count;
public:
CountFrom(int &n) : count(n) {}
int operator()() { return count++; }
};
int main() {
int state(10);
std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11, CountFrom(state));
return 0;
}
常规函数不能像函数对象那样保持状态。如果我没记错的话,这就是绕过没有lambdas和闭包的方法(在C ++ 11之前wikipedia section)......
答案 2 :(得分:1)
我认为关于仿函数的最好的事情是它们可以在内部存储信息。回到没有std::bind
的那些日子里,人们必须编写许多一元比较函数,以便将它传递给某些例程remove_if
。
答案 3 :(得分:0)
请参阅http://cs.stmarys.ca/~porter/csc/ref/stl/function_objects.html。
STL使用函数对象(仿函数)作为排序/搜索容器的回调。
函数是模板,因此更容易实现为类。尝试用函数指针说greater<T>
...考虑到STL中的容器也是模板。