C++中std::functional 使用場(chǎng)景
std::functional 是 C++ 標(biāo)準(zhǔn)庫(kù)中一個(gè)非常強(qiáng)大的工具,它提供了一種**類型擦除(type erasure)**機(jī)制,讓你能夠存儲(chǔ)、傳遞和調(diào)用任何可調(diào)用對(duì)象(callable)。
核心作用
1.統(tǒng)一的可調(diào)用對(duì)象包裝器
std::function 可以包裝任何可調(diào)用實(shí)體,只要簽名匹配:
- 普通函數(shù)
- Lambda 表達(dá)式
- 函數(shù)對(duì)象(仿函數(shù))
- 成員函數(shù)(通過(guò)
std::bind或 lambda) - 甚至其他
std::function
2.類型擦除
隱藏具體類型,只暴露接口。這使得你可以:
- 在容器中存儲(chǔ)不同類型的可調(diào)用對(duì)象
- 作為函數(shù)參數(shù)接受任意可調(diào)用對(duì)象
- 實(shí)現(xiàn)回調(diào)機(jī)制而不需要模板
主要使用場(chǎng)景
場(chǎng)景 1:回調(diào)函數(shù)(Callbacks)
#include <functional>
#include <iostream>
class Button {
std::function<void()> onClick_;
public:
void setOnClick(std::function<void()> callback) {
onClick_ = callback;
}
void click() { if (onClick_) onClick_(); }
};
// 使用
Button btn;
btn.setOnClick([]() { std::cout << "Clicked!\n"; });
btn.click();
場(chǎng)景 2:策略模式 / 算法注入
#include <functional>
#include <vector>
#include <algorithm>
void processData(std::vector<int>& data,
std::function<bool(int)> filter,
std::function<int(int)> transform) {
// 先過(guò)濾
data.erase(std::remove_if(data.begin(), data.end(),
[&](int x) { return !filter(x); }), data.end());
// 再轉(zhuǎn)換
for (auto& x : data) x = transform(x);
}
// 使用
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
processData(nums,
[](int x) { return x % 2 == 0; }, // 只保留偶數(shù)
[](int x) { return x * x; } // 平方
);
場(chǎng)景 3:事件系統(tǒng) / 觀察者模式
#include <functional>
#include <vector>
#include <string>
class EventSystem {
std::vector<std::function<void(const std::string&)>> listeners_;
public:
void subscribe(std::function<void(const std::string&)> listener) {
listeners_.push_back(listener);
}
void emit(const std::string& event) {
for (auto& listener : listeners_) {
listener(event);
}
}
};
// 使用
EventSystem events;
events.subscribe([](const std::string& e) {
std::cout << "Logger: " << e << "\n";
});
events.subscribe([](const std::string& e) {
std::cout << "Metrics: recorded " << e << "\n";
});
場(chǎng)景 4:延遲執(zhí)行 / 任務(wù)隊(duì)列
#include <functional>
#include <queue>
#include <iostream>
class TaskQueue {
std::queue<std::function<void()>> tasks_;
public:
void addTask(std::function<void()> task) {
tasks_.push(task);
}
void runAll() {
while (!tasks_.empty()) {
tasks_.front()();
tasks_.pop();
}
}
};
// 使用
TaskQueue queue;
queue.addTask([]() { std::cout << "Task 1\n"; });
queue.addTask([]() { std::cout << "Task 2\n"; });
queue.runAll();
場(chǎng)景 5:綁定成員函數(shù)
#include <functional>
#include <iostream>
class Calculator {
public:
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
};
// 使用 std::bind
Calculator calc;
auto addFunc = std::bind(&Calculator::add, &calc,
std::placeholders::_1, std::placeholders::_2);
std::cout << addFunc(3, 4); // 7
// 或者使用 lambda(更推薦,性能更好)
auto multiplyFunc = [&calc](int a, int b) {
return calc.multiply(a, b);
};
std::functionvs 模板 vs 裸函數(shù)指針
| 特性 | std::function | 模板 | 裸函數(shù)指針 |
|---|---|---|---|
| 類型擦除 | ? 是 | ? 否 | ? 是(但只能指向函數(shù)) |
| 存儲(chǔ) Lambda | ? 可以 | ? 可以 | ? 不行(除非無(wú)捕獲) |
| 運(yùn)行時(shí)開銷 | 有(虛函數(shù)調(diào)用) | 無(wú) | 無(wú) |
| 編譯時(shí)類型檢查 | 弱(運(yùn)行時(shí)可能拋 bad_function_call) | 強(qiáng) | 強(qiáng) |
| 存儲(chǔ)在容器中 | ? 容易 | ? 難(需要類型擦除) | ? 可以 |
最佳實(shí)踐
優(yōu)先使用模板:如果不需要存儲(chǔ)可調(diào)用對(duì)象,用模板參數(shù)更高效
// 更好:零開銷 template<typename Func> void execute(Func&& f) { f(); } // 有開銷:類型擦除 void execute(std::function<void()> f) { f(); }檢查空狀態(tài):調(diào)用前確保
std::function不為空if (func) func(); // 或 if (func != nullptr)
注意開銷:
std::function通常使用小對(duì)象優(yōu)化(SOO),但大對(duì)象會(huì)堆分配C++23 替代:考慮使用
std::move_only_function(僅移動(dòng))或std::copyable_function
std::functional 的核心價(jià)值在于靈活性——當(dāng)你需要在運(yùn)行時(shí)決定調(diào)用什么、或者需要在容器中存儲(chǔ)可調(diào)用對(duì)象時(shí),它是不可或缺的工具。
到此這篇關(guān)于C++中std::functional 使用場(chǎng)景的文章就介紹到這了,更多相關(guān)C++ std::functional 使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文帶你學(xué)習(xí)C/C++中的<Windows.h>庫(kù)
c語(yǔ)言 #include<windows.h>是寫window程序需要的重要頭文件,下面這篇文章主要給大家介紹了C/C++中<Windows.h>庫(kù)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01
C語(yǔ)言強(qiáng)制類型轉(zhuǎn)換規(guī)則實(shí)例詳解
強(qiáng)制類型轉(zhuǎn)換是把變量從一種類型轉(zhuǎn)換為另一種數(shù)據(jù)類型,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言強(qiáng)制類型轉(zhuǎn)換的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
C++自定義(手撕)vector類實(shí)現(xiàn)過(guò)程
文章介紹了C++中std::vector的簡(jiǎn)化實(shí)現(xiàn),涵蓋模板類定義、動(dòng)態(tài)數(shù)組管理、構(gòu)造析構(gòu)函數(shù)、深拷貝機(jī)制、迭代器及容量操作等核心內(nèi)容,旨在通過(guò)手動(dòng)實(shí)現(xiàn)理解其內(nèi)存管理原理和底層實(shí)現(xiàn)邏輯2025-09-09
opencv?C++模板匹配的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了opencv?C++模板匹配的簡(jiǎn)單實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
Vscode中接入Deepseek的實(shí)現(xiàn)
本文主要介紹了Vscode中接入Deepseek的實(shí)現(xiàn),包括登錄Deepseek官網(wǎng)、申請(qǐng)APIKEY、安裝和配置VSCode插件,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
C++ 基礎(chǔ)編程之十進(jìn)制轉(zhuǎn)換為任意進(jìn)制及操作符重載
這篇文章主要介紹了C++ 基礎(chǔ)編程之十進(jìn)制轉(zhuǎn)換為任意進(jìn)制及操作符重載的相關(guān)資料,需要的朋友可以參考下2017-02-02
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的學(xué)生學(xué)籍管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的學(xué)生學(xué)籍管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07

