亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我應該在C ++中使用std :: function還是函數指針?

我應該在C ++中使用std :: function還是函數指針?

C++
米琪卡哇伊 2019-11-05 15:18:05
在C ++中實現回調函數時,我仍應使用C樣式函數指針:void (*callbackFunc)(int);或者我應該使用std :: function:std::function< void(int) > callbackFunc;
查看完整描述

3 回答

?
躍然一笑

TA貢獻1826條經驗 獲得超6個贊

簡而言之,std::function除非有理由不要使用。


函數指針的缺點是無法捕獲某些上下文。例如,您將無法通過lambda函數作為捕獲某些上下文變量的回調(但是如果不捕獲任何上下文變量,它將起作用)。因此也不可能調用對象的成員變量(即非靜態的),因為this需要捕獲對象(-pointer)。(1)


std::function(因為C ++ 11)主要用于存儲函數(將其傳遞就不需要存儲它)。因此,如果要將回調存儲在例如成員變量中,則可能是最佳選擇。但是,如果您不存儲它,那么它是一個不錯的“首選”,盡管它的缺點是在調用時會引入一些(非常小的)開銷(因此,在性能非常關鍵的情況下,這可能是個問題,但在大多數情況下它不應該)。這是非常“通用的”:如果您非常關心一致且易讀的代碼,又不想考慮所做的每一個選擇(即想保持簡單),請使用std::function傳遞的每個函數。


考慮第三個選項:如果您要實現一個小的函數,然后通過提供的回調函數報告某些內容,請考慮一個template參數,該參數可以是任何可調用的對象,即函數指針,函子,lambda,一個std::function缺點是這里的(外部)函數成為模板,因此需要在標頭中實現。另一方面,您得到的好處是可以內聯對回調的調用,因為(外部)函數的客戶端代碼“看到”了對回調的調用,將提供確切的類型信息。


具有模板參數的版本的示例(對于C ++ 11之前的版本,請寫&而不是&&):


template <typename CallbackFunction>

void myFunction(..., CallbackFunction && callback) {

    ...

    callback(...);

    ...

}

正如您在下表中看到的,它們都有優點和缺點:


+-------------------+--------------+---------------+----------------+

|                   | 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)  |               |                |

+-------------------+--------------+---------------+----------------+

(1)存在克服此限制的解決方法,例如,將其他數據作為進一步的參數傳遞給您的(外部)函數:myFunction(..., callback, data)will call callback(data)。這就是C樣式的“帶參數的回調”,這在C ++中是可行的(并且在WIN32 API中大量使用),但是應避免使用,因為我們在C ++中有更好的選擇。


(2)除非我們在談論類模板,否則存儲函數的類就是模板。但這意味著在客戶端,函數的類型決定了存儲回調的對象的類型,這在實際用例中幾乎從來不是一個選擇。


(3)對于C ++ 11之前的版本,請使用 boost::function


查看完整回答
反對 回復 2019-11-05
?
白衣染霜花

TA貢獻1796條經驗 獲得超10個贊

使用std::function存儲任意調用對象。它允許用戶提供回調所需的任何上下文。一個普通的函數指針沒有。


如果由于某種原因(也許是因為您想要C兼容的API)而確實需要使用普通函數指針,則應添加一個void * user_context參數,以便至少有可能(盡管不方便)訪問不直接傳遞給參數的狀態。功能。


查看完整回答
反對 回復 2019-11-05
  • 3 回答
  • 0 關注
  • 1606 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號