bind看這一篇就夠了

bind能干啥

bind作用于函數(shù)上(包括普通函數(shù)得院,類成員函數(shù)等),將函數(shù)改造為一個(gè)類的對(duì)象坑鱼,這個(gè)類里面實(shí)現(xiàn)了operator()操作符持灰,使得這個(gè)對(duì)象能像函數(shù)一樣能使用()調(diào)用。這樣有什么好處呢怎燥?
首先瘫筐,函數(shù)對(duì)象操作方式和函數(shù)幾乎一致,不會(huì)帶來新的語法難度铐姚。
其次策肝,函數(shù)對(duì)象可以預(yù)設(shè)函數(shù)的部分參數(shù),更加靈活。
最后驳糯,函數(shù)對(duì)象可以綁定到類的成員函數(shù)篇梭。

bind的使用方式

  • bind的返回值
    bind的返回值是一個(gè)函數(shù)對(duì)象,在需要得到一個(gè)返回值的地方酝枢,建議使用關(guān)鍵字auto接收返回值恬偷,如下:
void my_plus(int a, int b) {  }
auto f_int = std::bind(my_plus, std::placeholders::_1, 10);

但是如果需要出現(xiàn)在形參聲明中,那么就必須完整寫出返回值的形式帘睦,如下:

std::function<void(int)> f_int = std::bind(my_plus, std::placeholders::_1,10);

上述寫法中袍患,void是該函數(shù)對(duì)象的操作符operator()返回值類型,這個(gè)類型應(yīng)該與原函數(shù)my_plus保持一致竣付。(int)表示該函數(shù)對(duì)象的操作符operator()的形參列表诡延。

  • bind綁定到普通函數(shù)
    用一個(gè)例子說明,對(duì)于給的int數(shù)組古胆,求大于10的元素個(gè)數(shù)肆良。
bool big_than(int a, int b) { return a > b; }
int for_each_array(std::vector<int>& vec, std::function<bool(int)> f) {
  int count = 0;
  for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
    if (f(*iter)) ++count;
  }
  return count;
}

int main() {
  auto f = std::bind(big_than, std::placeholders::_1, 10);
  std::vector<int> vec = {100,100,300,2,1,3};
  int res = for_each_array(vec, f);
}

上述代碼乍看沒有什么優(yōu)勢(shì),用函數(shù)指針也能輕易完成逸绎。但是如果需求中不僅需要求大于10的個(gè)數(shù)惹恃,還需要計(jì)算大于100的個(gè)數(shù),那么就不得不再建立一個(gè)新函數(shù)棺牧。而使用函數(shù)對(duì)象就可以輕易滿足動(dòng)態(tài)的需求巫糙。只要構(gòu)造一個(gè)新的函數(shù)對(duì)象即可。

參數(shù)對(duì)應(yīng)關(guān)系
  • 綁定類的靜態(tài)函數(shù)
    綁定靜態(tài)函數(shù)和普通函數(shù)類似颊乘,僅在構(gòu)造函數(shù)對(duì)象時(shí)的寫法略有不同
class T
{
public:
  bool big_than(int a, int b) { return a > b; }
};
int for_each_array(std::vector<int>& vec, std::function<bool(int)> f) {
  int count = 0;
  for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
    if (f(*iter)) ++count;
  }
  return count;
}

int main() {
  auto f = std::bind(&T::big_than, std::placeholders::_1, 10);
  std::vector<int> vec = {100,100,300,2,1,3};
  int res = for_each_array(vec, f);
}
  • 綁定到非靜態(tài)成員函數(shù)
class T
{
public:
  static bool big_than(int a, int b) { return a > b; }
  bool mem_big_than(int a, int b) { return a > b; }
};
int for_each_array(std::vector<int>& vec, std::function<bool(int)> f) {
  int count = 0;
  for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
    if (f(*iter)) ++count;
  }
  return count;
}

int main() {
  T t;
  auto f = std::bind(&T::mem_big_than, &t, std::placeholders::_1, 10);
  std::vector<int> vec = {100,100,300,2,1,3};
  int res = for_each_array(vec, f);
}

因?yàn)榉庆o態(tài)成員函數(shù)都是和某個(gè)對(duì)象相聯(lián)系参淹,所以在調(diào)用的時(shí)候必須有該類的對(duì)象在場(chǎng),即&t乏悄。此時(shí)還能在mem_big_than中使用對(duì)象t的屬性浙值。

bind使用場(chǎng)景

僅僅將一個(gè)函數(shù)變形為一個(gè)函數(shù)對(duì)象并沒有多大意義。重要的是可以把這個(gè)函數(shù)對(duì)象用于多變的場(chǎng)景檩小,又或者根據(jù)不同的情況構(gòu)造出不同的函數(shù)對(duì)象开呐,用來解決一系列相同性質(zhì)的問題。以達(dá)到復(fù)用性。
舉幾個(gè)例子。

  • 對(duì)象過濾器
    在某個(gè)應(yīng)用場(chǎng)景贸宏,你有一個(gè)manager管理一個(gè)對(duì)象的數(shù)組磕仅。可能你需要把滿足某些條件的對(duì)象摘取出來鸵荠,單獨(dú)處理冕茅。抑或是僅僅統(tǒng)計(jì)滿足條件的對(duì)象的數(shù)量,就完全可以使用bind。比如統(tǒng)計(jì)學(xué)生管理類中姨伤,年齡大于18歲的學(xué)生個(gè)數(shù)哨坪。自然地,你也可以在這個(gè)管理類中新加一個(gè)處理函數(shù)乍楚,但是除了大于18歲這個(gè)條件当编,還可能有其他條件,或者組合條件徒溪,在實(shí)際應(yīng)用中忿偷,這些條件可能比較復(fù)雜。使用bind后臊泌,處理起來更加靈活了鲤桥。
  • 回調(diào)處理函數(shù)
    在某個(gè)處理函數(shù)中,遇到某種情況渠概,可能需要在另一個(gè)類執(zhí)行某些操作茶凳,且這些操作的參數(shù)依賴與處理函數(shù)中的變量。如下所示:
T *obj = get_obj();
int param = argv[0];
int ret = deal_with_param(param);
if (ret) {
  obj->failed(std::bind(some_func, std::placeholders::_1, param));
}

在執(zhí)行deal_with_param時(shí)播揪,發(fā)生了錯(cuò)誤贮喧。需要在類T中做某些通知操作。這個(gè)通知的動(dòng)作依賴于當(dāng)下的參數(shù)param剪芍。這里的bind就起到了回調(diào)的作用塞淹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市罪裹,隨后出現(xiàn)的幾起案子饱普,更是在濱河造成了極大的恐慌,老刑警劉巖状共,帶你破解...
    沈念sama閱讀 212,294評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件套耕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡峡继,警方通過查閱死者的電腦和手機(jī)冯袍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碾牌,“玉大人康愤,你說我怎么就攤上這事〔奥穑” “怎么了征冷?”我有些...
    開封第一講書人閱讀 157,790評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)誓琼。 經(jīng)常有香客問我检激,道長(zhǎng)肴捉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,595評(píng)論 1 284
  • 正文 為了忘掉前任叔收,我火速辦了婚禮齿穗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饺律。我一直安慰自己窃页,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評(píng)論 6 386
  • 文/花漫 我一把揭開白布蓝晒。 她就那樣靜靜地躺著腮出,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芝薇。 梳的紋絲不亂的頭發(fā)上胚嘲,一...
    開封第一講書人閱讀 49,906評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音洛二,去河邊找鬼馋劈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晾嘶,可吹牛的內(nèi)容都是我干的妓雾。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼垒迂,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼械姻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起机断,我...
    開封第一講書人閱讀 37,797評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤楷拳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吏奸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欢揖,經(jīng)...
    沈念sama閱讀 44,250評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評(píng)論 2 327
  • 正文 我和宋清朗相戀三年奋蔚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了她混。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,711評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡泊碑,死狀恐怖坤按,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情馒过,我是刑警寧澤臭脓,帶...
    沈念sama閱讀 34,388評(píng)論 4 332
  • 正文 年R本政府宣布,位于F島的核電站沉桌,受9級(jí)特大地震影響谢鹊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜留凭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評(píng)論 3 316
  • 文/蒙蒙 一佃扼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔼夜,春花似錦兼耀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至匠题,卻和暖如春拯坟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背韭山。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評(píng)論 1 266
  • 我被黑心中介騙來泰國打工郁季, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钱磅。 一個(gè)月前我還...
    沈念sama閱讀 46,461評(píng)論 2 360
  • 正文 我出身青樓梦裂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親盖淡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子年柠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評(píng)論 2 350