C++中的bind實(shí)踐代碼
1.std::bind是什么?
簡(jiǎn)單來說,std::bind 是一個(gè)函數(shù)適配器(Adapter)。
核心作用是“預(yù)先固定”一個(gè)函數(shù)的某些參數(shù),從而生成一個(gè)新的函數(shù)對(duì)象。
你可以把它想象成一個(gè)模具:原來的函數(shù)需要 3 個(gè)原料,你先塞進(jìn)去 1 個(gè)固定的原料,剩下的 2 個(gè)留空(占位),這就變成了一個(gè)只需要 2 個(gè)原料的新工具。
2. 核心機(jī)制:占位符 (std::placeholders)
要使用 std::bind,必須先認(rèn)識(shí)它的搭檔:占位符。
它們位于 std::placeholders 命名空間下,通常寫成 _1, _2, _3...
_1:代表新函數(shù)被調(diào)用時(shí)的第 1 個(gè)參數(shù)。_2:代表新函數(shù)被調(diào)用時(shí)的第 2 個(gè)參數(shù)。- 以此類推。
3. 代碼實(shí)戰(zhàn)
我們需要包含頭文件:
#include <functional> using namespace std::placeholders; // 方便使用 _1, _2
場(chǎng)景 A:固定參數(shù)(減少參數(shù)個(gè)數(shù))
假設(shè)你有一個(gè)減法函數(shù),你希望得到一個(gè)“減去 10”的專用函數(shù)。
#include <iostream>
#include <functional>
using namespace std::placeholders;
int sub(int a, int b) {
return a - b;
}
int main() {
// 使用 bind:
// 我們把 sub 的第二個(gè)參數(shù) b 固定死為 10
// _1 代表新函數(shù) sub_ten 的第一個(gè)參數(shù),它會(huì)被填入 sub 的第一個(gè)位置 a
auto sub_ten = std::bind(sub, _1, 10);
// 調(diào)用新函數(shù):
// 實(shí)際執(zhí)行的是: sub(20, 10)
std::cout << sub_ten(20) << std::endl; // 輸出 10
return 0;
}場(chǎng)景 B:參數(shù)重排(改變參數(shù)順序)
std::bind 甚至可以顛倒參數(shù)的順序。
// 還是上面的 sub(a, b) -> a - b // 這次我們交換位置: // sub 的第一個(gè)參數(shù) (a) 吃新函數(shù)的第二個(gè)參數(shù) (_2) // sub 的第二個(gè)參數(shù) (b) 吃新函數(shù)的第一個(gè)參數(shù) (_1) auto reverse_sub = std::bind(sub, _2, _1); // 調(diào)用: reverse_sub(10, 20) // 實(shí)際執(zhí)行: sub(20, 10) -> 20 - 10 std::cout << reverse_sub(10, 20) << std::endl; // 輸出 10
場(chǎng)景 C:綁定成員函數(shù)(最常用的舊式寫法)
這是 std::bind 在 C++11 初期最常見的用途:配合 std::function 做回調(diào),特別是為了綁定 this 指針。
class Hero {
public:
void heal(int amount) {
std::cout << "Healed " << amount << " hp." << std::endl;
}
};
int main() {
Hero myHero;
// 綁定成員函數(shù)
// 參數(shù)1:成員函數(shù)指針 &Hero::heal
// 參數(shù)2:對(duì)象實(shí)例的地址 &myHero (作為隱式的 this)
// 參數(shù)3:占位符 _1 (將來傳進(jìn)來的 amount)
std::function<void(int)> func = std::bind(&Hero::heal, &myHero, _1);
func(50); // 輸出: Healed 50 hp.
}4. 這里的坑:參數(shù)拷貝 vs 引用
這是 std::bind 最容易出錯(cuò)的地方。std::bind 默認(rèn)是按值拷貝參數(shù)的!
如果你想綁定的參數(shù)是一個(gè)引用,或者是一個(gè)無法拷貝的對(duì)象
(比如 unique_ptr),你必須顯式使用 std::ref 或 std::cref (const ref)。
void updateScore(int& score, int val) {
score += val;
}
int main() {
int myScore = 100;
// 錯(cuò)誤寫法!
// auto update = std::bind(updateScore, myScore, _1);
// 這會(huì)導(dǎo)致 bind 內(nèi)部拷貝了一份 myScore,原本的 myScore 不會(huì)變。
// 正確寫法:使用 std::ref
auto update = std::bind(updateScore, std::ref(myScore), _1);
update(20);
std::cout << myScore << std::endl; // 輸出 120
}5. 靈魂拷問:為什么現(xiàn)在不推薦用std::bind?
既然 Lambda 講完了,Bind 也講完了,我們對(duì)比一下。現(xiàn)在 C++ 社區(qū)(包括官方指南)強(qiáng)烈建議能用 Lambda 就別用 Bind。
原因如下:
- 可讀性差:
bind(func, _2, 10, _1)這種寫法像是猜謎語,你需要腦補(bǔ)參數(shù)填空的對(duì)應(yīng)關(guān)系。而 Lambda[](int x, int y) { return func(y, 10, x); }一目了然。 - 容易出錯(cuò):剛才提到的
std::ref問題,很容易忘記寫,導(dǎo)致很多隱晦的 Bug。而 Lambda 的捕獲列表[&]顯式且直觀。 - 編譯器優(yōu)化:Lambda 表達(dá)式對(duì)編譯器來說是透明的代碼塊,容易內(nèi)聯(lián)優(yōu)化。
std::bind生成的是復(fù)雜的模板對(duì)象,編譯器優(yōu)化起來比較費(fèi)勁,有時(shí)會(huì)導(dǎo)致生成的二進(jìn)制代碼更大、更慢。
對(duì)比示例:
// 任務(wù):調(diào)用 object.process(data)
// 方式 1: std::bind (舊時(shí)代)
auto task1 = std::bind(&MyClass::process, &object, data);
// 方式 2: Lambda (新時(shí)代 - 推薦)
auto task2 = [&object, data]() { object.process(data); };到此這篇關(guān)于C++中的bind代碼實(shí)踐的文章就介紹到這了,更多相關(guān)C++ bind內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++自主分配出現(xiàn)double free or corruption問題解決
這篇文章主要為大家介紹了C/C++出現(xiàn)double free or corruption問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
使用mmap實(shí)現(xiàn)多進(jìn)程對(duì)大文件拷貝
這篇文章主要介紹了使用mmap實(shí)現(xiàn)多進(jìn)程對(duì)大文件拷貝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器
計(jì)算器是我們生活中很常見的東西,它可以由多種語言多種方式來實(shí)現(xiàn)。本文主要介紹的是基于C++語言,由QT實(shí)現(xiàn)的可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器,需要的可以參考一下2022-12-12

