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ì)象即可。
- 綁定類的靜態(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)的作用塞淹。