回调函数(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)不能处理在同一个容器中支持异质类型,是一个道理。
原文地址:http://blog.csdn.net/xushiweizh/article/details/1519828
分享到:
相关推荐
### 回调函数Callback Function #### 一、基本概念 **回调函数**是一种常见的编程模式,广泛应用于多种编程语言中,特别是在C/C++等语言中非常常见。简单来说,回调函数是指通过函数指针传递的一个函数,该函数会...
本文实例分析了C++中回调函数(CallBack)的用法。分享给大家供大家参考。具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。 其错误是普通的C++成员函数都隐含了一个传递...
综上所述,JNI回调函数Callback是Android开发中连接Java和C/C++的重要方式,它使得两个世界之间的通信更为灵活,能够实现更多复杂的逻辑。在实际应用中,开发者需要熟练掌握JNI的基础知识,并了解如何安全有效地使用...
可能包含了具体的信号槽连接示例,而`mainwindow.ui`则是Qt Designer生成的用户界面文件,`callback.pro`和`callback.pro.user`则是项目配置文件,它们共同构成了一个关于Qt回调函数使用的实例项目。
尽管在C++中还有其他替代方案,如虚拟函数和函数对象,但回调函数仍然是许多系统和库的核心部分,尤其在需要与C代码交互或处理遗留接口时。理解和熟练使用回调函数是成为熟练程序员的关键技能之一。
在【标题】"回调函数Callback Function.pdf"中,主要讨论了回调函数的概念、使用场景以及简单的实现方式。在【描述】中虽然没有给出具体内容,但从标签"毕业设计 cs"可以看出,这是针对计算机科学(CS)领域,尤其是...
然而,虽然回调函数在C++中是有用的,但在C++中更推荐使用虚函数或函数对象(functor)来替代回调函数,特别是在面向对象编程中,因为它们提供了更好的封装和类型安全。虚函数允许通过继承和多态性实现动态绑定,而...
- **定义回调函数类型**:首先,我们需要定义一个函数原型,表示回调函数的参数和返回值类型。例如: ```c typedef void (*CallbackType)(int data); // 定义一个接受整型参数并无返回值的回调函数类型 ``` - **声明...
通过以上步骤,你已经掌握了在Linux环境下编写回调函数和制作库文件的基本方法。在实际开发中,可以根据项目需求进行扩展和优化,比如添加错误处理、多线程支持等。希望这篇教程能帮助你更好地理解和运用这些技术。
通过阅读和学习这些示例,开发者可以了解如何在自己的项目中应用PB回调函数和多线程技术。 总结来说,PB回调函数在多线程环境中的应用涉及到数据序列化、事件处理、线程安全以及组件化开发等多个方面。通过合理利用...
- **Halcon API**:Halcon 提供给用户的编程接口,包括各种图像处理函数和设备控制函数。 #### 四、C# 示例代码详解 本节将详细解析给定的部分代码示例,以便更好地理解整个过程。 ##### 4.1 初始化与加载 ```...
网上的回调函数都是API例子,学习函数指针倒是不错,可是很难让初学者立即应用。常见的情况是辅线程完成某事件后需要“通知”主界面,比如常见的进度条——线程中完成一定的进度后即通知主界面显示到一定的刻度。本...
总结起来,Delphi的DLL回调函数是实现模块化和通信的重要手段,通过传递函数指针,DLL可以将控制权交还给调用者,允许调用者在适当的时候处理结果或事件。这种技术在软件开发中有着广泛的应用,尤其是在需要高效、...
总结一下,回调函数是Java和Android开发中的核心概念,它们使我们能够以松耦合的方式处理事件和异步操作。通过理解并熟练运用回调函数,开发者可以构建更灵活、响应更快的应用程序。在实际项目中,要善于利用回调来...
回调函数通常用于异步编程,事件处理或者作为参数传递,使得代码更加灵活和可扩展。接下来,我们将深入探讨C#中实现回调函数的原理、方式以及应用场景。 首先,我们需要理解什么是回调函数。回调函数本质上就是一个...
在编程领域,动态链接库(Dynamic Link Library,简称 DLL)是一种可执行文件格式,它包含可供其他程序调用的函数和资源。DLL 文件允许多个应用程序共享同一代码库,从而节省内存并提高系统效率。VC++6.0 是 ...
在JavaScript的世界里,jQuery(简称JQ)是一个广泛使用的库,极大地简化了...理解和熟练运用回调函数是每个jQuery开发者必备的技能。在进行项目实践时,可以结合压缩包中的`demo`文件进行学习,进一步巩固这些概念。
通常,回调函数的原型会在调用者和被调用者之间共享。例如: ```cpp typedef int (__stdcall *CallbackFunc)(int, int); ``` 这里定义了一个名为`CallbackFunc`的函数指针类型,它接受两个`int`类型的参数,并...
在C#中,回调函数同样被广泛使用,尤其是在异步编程、事件处理和自定义算法中。本示例将通过VS2013环境,探讨如何在C#中实现和应用回调函数。 首先,我们需要理解回调函数的基本概念。回调函数本质上是一个在其他...