C++回调函数(callback)与仿函数(functor)的异同
回调函数(callback)与仿函数(functor)很多时候从用途上来看很相似,以致于我们经常 将它们相提并论。例如:
仿函数(functor)之所以称为仿函数,是因为这是一种利用某些类对象支持operator()的 特性,来达到模拟函数调用效果的技术。 如果这里vec, vec2这两个vector的内容一样,那么从执行结果看,使用回调函数compare 与使用仿函数comparer是一样的。 那么,我们应该用回调,还是用仿函数? 很多人都说用仿函数吧,回调函数是丑陋的,代码不太象C++风格。 但其实问题的本质不是在代码风格上,仿函数与回调函数各有利弊,不能一概而论。 仿函数(functor)的优点 我的建议是,如果可以用仿函数实现,那么你应该用仿函数,而不要用回调。原因在于: 仿函数可以不带痕迹地传递上下文参数。而回调技术通常使用一个额外的void*参数传递 。这也是多数人认为回调技术丑陋的原因。 更好的性能。 仿函数技术可以获得更好的性能,这点直观来讲比较难以理解。你可能说,回调函数申明 为inline了,怎么会性能比仿函数差?我们这里来分析下。我们假设某个函数func(例如上 面的std::sort)调用中传递了一个回调函数(如上面的compare),那么可以分为两种情况 : func是内联函数,并且比较简单,func调用最终被展开了,那么其中对回调函数的调用也 成为一普通函数调用(而不是通过函数指针的间接调用),并且如果这个回调函数如果简单 ,那么也可能同时被展开。在这种情形下,回调函数与仿函数性能相同。 func是非内联函数,或者比较复杂而无法展开(例如上面的std::sort,我们知道它是快 速排序,函数因为存在递归而无法展开)。此时回调函数作为一个函数指针传入,其代码亦 无法展开。而仿函数则不同。虽然func本身复杂不能展开,但是func函数中对仿函数的调用 是编译器编译期间就可以确定并进行inline展开的。因此在这种情形下,仿函数比之于回调 函数,有着更好的性能。并且,这种性能优势有时是一种无可比拟的优势(对于std::sort就 是如此,因为元素比较的次数非常巨大,是否可以进行内联展开导致了一种雪崩效应)。 仿函数(functor)不能做的? 话又说回来了,仿函数并不能完全取代回调函数所有的应用场合。例如,我在 std::AutoFreeAlloc中使用了回调函数,而不是仿函数,这是因为AutoFreeAlloc要容纳异质 的析构函数,而不是只支持某一种类的析构。这和模板(template)不能处理在同一个容器 中支持异质类型,是一个道理。 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |