void (*callbackFunc)(int); 可能是一个 C 风格的回调函数,但它是一个糟糕的设计,非常不可用。
精心设计的 C 风格回调看起来像 void (*callbackFunc)(void*, int); -- 它有一个 void* 以允许执行回调的代码在函数之外保持状态。不这样做会强制调用者全局存储状态,这是不礼貌的。
std::function< int(int) > 在大多数实现中最终比int(*)(void*, int) 调用更昂贵。然而,对于某些编译器来说,内联更加困难。有std::function 克隆实现可以与函数指针调用开销相媲美(请参阅“最快的委托”等),这些实现可能会进入库。
现在,回调系统的客户端通常需要在创建和删除回调时设置资源并处理它们,并了解回调的生命周期。 void(*callback)(void*, int) 不提供这个。
有时这可以通过代码结构(回调的生命周期有限)或通过其他机制(注销回调等)获得。
std::function 提供了一种有限生命周期管理的方法(对象的最后一个副本在被遗忘时消失)。
一般来说,我会使用std::function,除非出现性能问题。如果他们这样做了,我会首先寻找结构变化(而不是每像素回调,如何根据您传递给我的 lambda 生成扫描线处理器?这应该足以将函数调用开销减少到微不足道的水平。 )。然后,如果它仍然存在,我会根据可能的最快委托写一个delegate,看看性能问题是否消失。
我主要只将函数指针用于遗留 API,或者用于创建 C 接口以在不同编译器生成的代码之间进行通信。当我实现跳转表、类型擦除等时,我还将它们用作内部实现细节:当我同时生产和使用它,并且没有将它暴露在外部以供任何客户端代码使用时,函数指针可以满足我的所有需要.
请注意,您可以编写将 std::function<int(int)> 转换为 int(void*,int) 样式回调的包装器,假设有适当的回调生命周期管理基础架构。因此,作为任何 C 风格回调生命周期管理系统的冒烟测试,我会确保包装 std::function 工作得相当好。