卓航论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 170|回复: 3
打印 上一主题 下一主题

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

[复制链接]
[至尊红钻5级]发帖数量≥8000篇 [未点亮至尊黄钻]威望不足10点 [未点亮至尊蓝钻]在线时间不足10小时 [未点亮至尊绿钻]贡献度不足10点 [至尊紫钻4级]金币≥20000个 [未点亮至尊粉钻]精华贴数不足10贴 [未点亮至尊黑钻]活跃不足8个
 等级: 
 级别: 论坛元老
 UID:  7   [未点亮普号显示]钻石不足3个
 阁 分: 36567
 阁 望: 0
 阁 献: 0
 活 跃: 0
 发 贴: 12405 (0)
 阁 币: 24162  
性 别: I'm 火星人!
阅读权限: 90
在线时长: 0 小时
注册时间: 2016-10-16
最后登录: 2016-10-18
go
楼主
发表于 2016-10-17 16:23:51 |只看该作者 |倒序浏览
本帖发表于 2016-10-17 16:23:51...阅读 171 人...加油,亲爱的楼主:[db:作者]
回调函数(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[i] 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)不能处理在同一个容器 中支持异质类型,是一个道理。
分享到: QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏0 支持支持0 反对反对0

使用道具 举报

[至尊红钻3级]发帖数量≥1000篇 [未点亮至尊黄钻]威望不足10点 [未点亮至尊蓝钻]在线时间不足10小时 [未点亮至尊绿钻]贡献度不足10点 [未点亮至尊紫钻]金币不足100个 [未点亮至尊粉钻]精华贴数不足10贴 [未点亮至尊黑钻]活跃不足8个
 等级: 
 级别: 金牌会员
 UID:  5   [未点亮普号显示]钻石不足3个
 阁 分: 1295
 阁 望: 0
 阁 献: 0
 活 跃: 0
 发 贴: 1242 (0)
 阁 币: 53  
性 别: I'm 火星人!
阅读权限: 70
在线时长: 0 小时
注册时间: 2016-10-15
最后登录: 2016-10-18
沙发
发表于 2016-10-18 00:06:28 |只看该作者
本回复帖发表于 2016-10-18 00:06:28,感谢方丹果舞对本帖的认真回复,你的回复是对楼主莫大的鼓舞
我是个凑数的。。。

使用道具 举报

[至尊红钻2级]发帖数量≥100篇 [未点亮至尊黄钻]威望不足10点 [未点亮至尊蓝钻]在线时间不足10小时 [未点亮至尊绿钻]贡献度不足10点 [未点亮至尊紫钻]金币不足100个 [未点亮至尊粉钻]精华贴数不足10贴 [未点亮至尊黑钻]活跃不足8个
 等级: 
 级别: 注册会员
 UID:  15   [未点亮普号显示]钻石不足3个
 阁 分: 135
 阁 望: 1
 阁 献: 3
 活 跃: 0
 发 贴: 120 (0)
 阁 币: 10  
性 别: I'm Boy
阅读权限: 20
在线时长: 5 小时
注册时间: 2011-1-6
最后登录: 2016-10-21
板凳
发表于 2016-10-19 19:33:13 |只看该作者
本回复帖发表于 2016-10-19 19:33:13,感谢eden002对本帖的认真回复,你的回复是对楼主莫大的鼓舞
过来看看的

使用道具 举报

[至尊红钻2级]发帖数量≥100篇 [未点亮至尊黄钻]威望不足10点 [未点亮至尊蓝钻]在线时间不足10小时 [未点亮至尊绿钻]贡献度不足10点 [未点亮至尊紫钻]金币不足100个 [未点亮至尊粉钻]精华贴数不足10贴 [未点亮至尊黑钻]活跃不足8个
 等级: 
 级别: 注册会员
 UID:  53   [未点亮普号显示]钻石不足3个
 阁 分: 137
 阁 望: 9
 阁 献: 9
 活 跃: 0
 发 贴: 100 (0)
 阁 币: 10  
性 别: I'm 火星人!
阅读权限: 20
在线时长: 0 小时
注册时间: 2011-1-6
最后登录: 2016-10-21
地板
发表于 2016-10-21 22:39:14 |只看该作者
本回复帖发表于 2016-10-21 22:39:14,感谢bangat对本帖的认真回复,你的回复是对楼主莫大的鼓舞
好好 学习了 确实不错

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1、请认真发帖,禁止回复纯表情,纯数字等无意义的内容!帖子内容不要太简单!
2、提倡文明上网,净化网络环境!抵制低俗不良违法有害信息。
3、每个贴内连续回复请勿多余3贴,每个版面回复请勿多余10贴!
4、如果你对主帖作者的帖子不屑一顾的话,请勿回帖。谢谢合作!

手机版| 百度搜索:vkee.pw

2012-2015 卓航旗下 GMT+8, 2024-6-17 02:05 , Processed in 4.930441 second(s), 30 queries . Powered by Discuz! X3.2  

禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.如遇版权问题,请及时联系站长(QQ:5213513)

今天是: | 本站已经安全运行: //这个地方可以改颜色

快速回复 返回顶部 返回列表