我应该使用std ::函数还是C ++中的函数指针? [英] Should I use std::function or a function pointer in C++?

查看:111
本文介绍了我应该使用std ::函数还是C ++中的函数指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中实现回调函数时,应该仍然使用C风格函数指针:

When implementing a callback function in C++, should I still use the C-style function pointer:

void (*callbackFunc)(int);

或者我应该使用std :: function:

Or should I make use of std::function:

std::function< void(int) > callbackFunc;


推荐答案

函数指针的缺点是不是

Function pointers have the disadvantage of not being able to capture some context. You won't be able to for example pass a lambda function as a callback which captures some context variables (but it will work if it doesn't capture any). Calling a member variable of an object (i.e. non-static) is thus also not possible, since the object (this-pointer) needs to be captured.(1)

std :: function (自C ++ 11起)存储一个函数(传递它不需要它被存储)。因此,如果你想存储回调例如在一个成员变量,它可能是你最好的选择。但是如果你不存储它,它是一个很好的第一选择,虽然它的缺点是引入一些(非常小)开销被调用时(所以在一个非常性能关键的情况下它可能是一个问题,但在大多数它不应该)。这是非常普遍:如果你关心一致的可读代码,以及不想想你所做的每一个选择(即想保持简单),使用 std ::

std::function (since C++11) is primarily to store a function (passing it around doesn't require it to be stored). Hence if you want to store the callback for example in a member variable, it's probably your best choice. But also if you don't store it, it's a good "first choice" although it has the disadvantage of introducing some (very small) overhead when being called (so in a very performance-critical situation it might be a problem but in most it should not). It is very "universal": if you care a lot about consistent and readable code as well as don't want to think about every choice you make (i.e. want to keep it simple), use std::function for every function you pass around.

想想第三个选项:如果你要实现一个小函数,然后报告一些东西通过提供的回调函数考虑模板参数,然后可以是任何可调用对象,即函数指针,函子,lambda, std :: function ,...这里的缺点是你的(外部)函数成为一个模板,因此需要在标题中实现。另一方面,你的优点是调用回调函数可以被内联,因为你的(外部)函数的客户端代码看到对回调的调用将有准确的类型信息。

Think about a third option: If you're about to implement a small function which then reports something via the provided callback function, consider a template parameter, which can then be any callable object, i.e. a function pointer, a functor, a lambda, a std::function, ... Drawback here is that your (outer) function becomes a template and hence needs to be implemented in the header. On the other hand you get the advantage that the call to the callback can be inlined, as the client code of your (outer) function "sees" the call to the callback will the exact type information being available.

具有模板参数的版本示例(写入& 而不是&& for pre-C ++ 11):

Example for the version with the template parameter (write & instead of && for pre-C++11):

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






如下表所示,所有的都有自己的优点和缺点:


As you can see in the following table, all of them have their advantages and disadvantages:

+-------------------+--------------+---------------+----------------+
|                   | function ptr | std::function | template param |
+===================+==============+===============+================+
| can capture       |    no(1)     |      yes      |       yes      |
| context variables |              |               |                |
+-------------------+--------------+---------------+----------------+
| no call overhead  |     yes      |       no      |       yes      |
| (see comments)    |              |               |                |
+-------------------+--------------+---------------+----------------+
| can be inlined    |      no      |       no      |       yes      |
| (see comments)    |              |               |                |
+-------------------+--------------+---------------+----------------+
| can be stored     |     yes      |      yes      |      no(2)     |
| in class member   |              |               |                |
+-------------------+--------------+---------------+----------------+
| can be implemented|     yes      |      yes      |       no       |
| outside of header |              |               |                |
+-------------------+--------------+---------------+----------------+
| supported without |     yes      |     no(3)     |       yes      |
| C++11 standard    |              |               |                |
+-------------------+--------------+---------------+----------------+
| nicely readable   |      no      |      yes      |      (yes)     |
| (my opinion)      | (ugly type)  |               |                |
+-------------------+--------------+---------------+----------------+



< hr>

(1)存在克服这个限制的解决方法,例如将附加数据作为进一步的参数传递给你的(外部)函数: myFunction ...,callback,data)将调用 callback(data)。这是C风格的带参数的回调,这是可能在C + +(和在WIN32 API中大量使用的方式),但应该避免,因为我们有更好的选项在C ++。


(1) Workarounds exist to overcome this limitation, for example passing the additional data as further parameters to your (outer) function: myFunction(..., callback, data) will call callback(data). That's the C-style "callback with arguments", which is possible in C++ (and by the way heavily used in the WIN32 API) but should be avoided because we have better options in C++.

(2)除非我们在谈论类模板,即存储函数的类是一个模板。但这意味着在客户端,函数的类型决定了存储回调的对象的类型,这在实际使用中几乎从不是一个选项。

(3)对于pre-C ++ 11,请使用 boost :: function

这篇关于我应该使用std ::函数还是C ++中的函数指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆