科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件C++回调函数(callback)与仿函数(functor)的异同

C++回调函数(callback)与仿函数(functor)的异同

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文是有关C++回调函数(callback)与仿函数(functor)的异同。

作者:许式伟 来源:CSDN 2008年2月12日

关键字: 异同 functor CallBack Linux

  • 评论
  • 分享微博
  • 分享邮件

回调函数(callback)与仿函数(functor)很多时候从用途上来看很相似,以致于我们经常将它们相提并论。例如:

inline bool compare(int a, int b)
{
   
return a > b;
}
 
struct comparer {
  
bool operator()(int a, int b) const {
     
return a > b;
  }
};
 
void main()
{
   std::vector
<int> vec, vec2;
   std::sort(vec.begin(), vec.end(), compare);
   std::sort(vec2.begin(), vec2.end(), comparer());
}

仿函数(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)不能处理在同一个容器中支持异质类型,是一个道理。

 
查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章