問題描述
在C++中實現(xiàn)回調(diào)函數(shù)時,我是否還應(yīng)該使用C風格的函數(shù)指針:
When implementing a callback function in C++, should I still use the C-style function pointer:
void (*callbackFunc)(int);
或者我應(yīng)該使用 std::function:
Or should I make use of std::function:
std::function< void(int) > callbackFunc;
推薦答案
簡而言之,除非有理由不使用,否則請使用 std::function
.
函數(shù)指針的缺點是不能捕獲某些上下文.例如,您將無法將 lambda 函數(shù)作為捕獲某些上下文變量的回調(diào)傳遞(但如果它不捕獲任何上下文變量,它將起作用).因此,調(diào)用對象的成員變量(即非靜態(tài))也是不可能的,因為需要捕獲對象(this
-pointer).(1)
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 起)主要用于存儲一個函數(shù)(傳遞它不需要存儲它).因此,如果您想將回調(diào)存儲在例如成員變量中,這可能是您的最佳選擇.而且如果你不存儲它,它也是一個不錯的首選"盡管它的缺點是在調(diào)用時引入了一些(非常小的)開銷(因此在非常關(guān)鍵的性能情況下它可能是一個問題,但在大多數(shù)情況下它不應(yīng)該).它非常通用":如果您非常關(guān)心一致和可讀的代碼,并且不想考慮您所做的每一個選擇(即想要保持簡單),請使用 std::function
對于您傳遞的每個函數(shù).
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.
考慮第三種選擇:如果您要實現(xiàn)一個小函數(shù),然后通過提供的回調(diào)函數(shù)報告某些內(nèi)容,請考慮一個模板參數(shù),它可以是任何可調(diào)用的對象,即一個函數(shù)指針,一個函子,一個 lambda,一個 std::function
,......這里的缺點是你的(外部)函數(shù)變成了一個模板,因此需要在標題中實現(xiàn).另一方面,您可以獲得可以內(nèi)聯(lián)回調(diào)調(diào)用的優(yōu)勢,因為您的(外部)函數(shù)的客戶端代碼看到"了對回調(diào)的調(diào)用將提供可用的確切類型信息.
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.
帶有模板參數(shù)的版本示例(對于 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(...);
...
}
如下表所示,它們各有優(yōu)缺點:
As you can see in the following table, all of them have their advantages and disadvantages:
函數(shù)ptr | std::function | 模板參數(shù) | |
---|---|---|---|
可以捕獲上下文變量 | no1 | 是 | 是 |
沒有調(diào)用開銷(見評論) | 是 | no | 是 |
可以內(nèi)聯(lián)(見評論) | no | no | 是 |
可以存放在一個類成員中 | 是 | 是 | no2 |
可以在header之外實現(xiàn) | 是 | 是 | no |
不支持 C++11 標準 | 是 | no3 | 是 |
可讀性很好(我認為) | no | 是 | (是) |
(1) 存在克服此限制的解決方法,例如將附加數(shù)據(jù)作為進一步的參數(shù)傳遞給您的(外部)函數(shù):myFunction(..., callback, data)
將調(diào)用 callback(data)
.這是 C 風格的帶參數(shù)回調(diào)",這在 C++ 中是可能的(順便說一下,在 WIN32 API 中大量使用)但應(yīng)該避免,因為我們在 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) 除非我們談?wù)摰氖穷惸0?,即存儲函?shù)的類是模板.但這意味著在客戶端,函數(shù)的類型決定了存儲回調(diào)的對象的類型,這在實際用例中幾乎從來不是一個選項.
(3) 對于 C++11 之前的版本,使用 boost::function
這篇關(guān)于我應(yīng)該在 C++ 中使用 std::function 還是函數(shù)指針?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!