首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 回呼函數 vs 仿函數:效能、靈活度與適用場景深度比較

     編輯:關於C++

基本形式對比

// 回呼函數
inline bool compare(int a, int b) { return a > b; }

// 仿函數
struct comparer {
    bool operator()(int a, int b) const { return a > b; }
};

// 使用
std::sort(vec.begin(), vec.end(), compare);     // 函數指標
std::sort(vec2.begin(), vec2.end(), comparer()); // 仿函數物件

仿函數優勢

  1. 攜帶狀態 (上下文):仿函數可保存成員變數,無需額外 void* 參數傳遞上下文,介面更乾淨。
  2. 效能優勢 (關鍵):
    • 若演算法函式 (如 std::sort) 非內聯/遞迴無法展開,回呼函數以函數指標傳入,**無法內聯**,每次比較皆為間接呼叫。
    • 仿函數型別在編譯期已知,編譯器可將 operator() **內聯** 展開至演算法迴圈中,消除呼叫開銷。對 std::sort 這類比較次數極多 (O(n log n)) 的演算法,內聯帶來的效能提升呈雪崩式放大。

何時必須用回呼函數

  • **異質操作集合**:需在同一容器存放不同簽名/行為的可呼叫實體 (如 std::AutoFreeAlloc 存放異質解構函數)。模板仿函數型別固定,無法像函數指標那樣型別抹除。
  • **C 風格 API 介接**:回呼介面為 void (*)(void*) 時。
  • **動態載入插件**:透過 dlsym/GetProcAddress 取得函數指標。

決策指南

場景推薦理由
標準演算法 (sort, find_if 等)仿函數 / Lambda內聯優化、型別安全、可攜帶狀態
需儲存異質可呼叫物件std::function / 函數指標型別抹除、統一介面
C API 回呼函數指標ABI 相容
簡單無狀態邏輯Lambda (C++11+)就地定義、自動推導型別、可捕獲變數

現代 C++ 建議

C++11 起,Lambda 表達式 取代絕大多數手寫仿函數場景:

std::sort(v.begin(), v.end(), [](int a, int b){ return a > b; });

需要攜帶狀態時:

int threshold = 10;
std::copy_if(v.begin(), v.end(), out, [threshold](int x){ return x > threshold; });

僅在需要型別抹除 (存入容器、跨 DLL 介面) 時使用 std::function。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved