c++ - 我应该在 C++ 中使用 std::function 还是函数指针?

标签 c++ function c++11 callback std

在 C++ 中实现回调函数时,我是否仍应使用 C 风格的函数指针:

void (*callbackFunc)(int);

或者我应该使用 std::function :
std::function< void(int) > callbackFunc;

最佳答案

简而言之,使用 std::function 除非你有理由不这样做。
函数指针有的缺点无法捕获 一些上下文。例如,您将无法将 lambda 函数作为捕获某些上下文变量的回调传递(但如果它不捕获任何上下文变量,它将起作用)。因此,调用对象的成员变量(即非静态)也是不可能的,因为需要捕获对象(this -pointer)。(1)std::function (自 C++11 起)主要针对 店铺 一个函数(传递它不需要存储它)。因此,如果您想将回调存储在例如成员变量中,这可能是您的最佳选择。但是如果你不存储它,它也是一个很好的“首选”,尽管它的缺点是在调用时引入一些(非常小的)开销(所以在非常关键的情况下它可能是一个问题,但在大多数情况下)它不应该)。它非常“通用”:如果您非常关心一致和可读的代码,并且不想考虑您所做的每一个选择(即想要保持简单),请使用 std::function对于您传递的每个函数。
考虑第三种选择:如果您要实现一个小函数,然后通过提供的回调函数报告某些内容,请考虑 模板参数 ,它可以是任何可调用的对象,即函数指针、仿函数、lambda、std::function , ... 这里的缺点是您的(外部)函数变成了模板,因此需要在 header 中实现。另一方面,您可以获得可以内联回调调用的优势,因为(外部)函数的客户端代码“看到”回调调用将获得可用的确切类型信息。
带有模板参数的版本示例(对于 pre-C++11,写 & 而不是 &&):

template <typename CallbackFunction>
void myFunction(..., CallbackFunction && callback) {
    ...
    callback(...);
    ...
}

如下表所示,它们各有优缺点:



函数指针
标准::函数
模板参数


可以捕获上下文变量
1号
是的
是的

没有调用开销(见评论)
是的
没有
是的

可以内联(见评论)
没有
没有
是的

可以存储在类成员中
是的
是的
2号

可以在 header 之外实现
是的
是的
没有

不支持 C++11 标准
是的
3号
是的

可读性很好(我的意见)
没有
是的
(是的)


(1) 存在克服此限制的变通方法,例如将附加数据作为进一步参数传递给您的(外部)函数:myFunction(..., callback, data)将调用 callback(data) .这是 C 风格的“带参数回调”,这在 C++ 中是可能的(顺便说一下,在 WIN32 API 中大量使用)但应该避免,因为我们在 C++ 中有更好的选择。
(2) 除非我们谈论的是类模板,即您存储函数的类是模板。但这意味着在客户端,函数的类型决定了存储回调的对象的类型,这几乎不是实际用例的选项。
(3) 对于 C++11 之前的版本,使用 boost::function

关于c++ - 我应该在 C++ 中使用 std::function 还是函数指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25848690/

相关文章:

c++ - Metal - 针对内存延迟优化 GPU 矩阵乘法

c++ - 如何根据文件类型专门化小部件?

javascript - Reactjs 可以像更改 Prop 一样更改 onclick 函数名称

c - 在我尝试用 C 编写的简单函数中出现 "unused variable"和 "undeclared identifier"错误,但我不明白为什么

奇异硬件上的 C++11

C++多维映射: How to acces 'inner' maps?

c++ - Qt - 对非 opengl 小部件的影响

c - 函数指针为什么要使用它?

c++ - 为什么 std::string 是标准布局类型?

c++ - 通过const引用传递shared_ptr是线程安全的吗?