概述
bind
函數(shù)可以看作一個通用的函數(shù)適配器领铐,所謂適配器循签,即使某種事物的行為類似于另外一種事物的一種機制帅涂,如容器適配器:stack(棧)
、queue(隊列)
尤蛮、priority_queue(優(yōu)先級隊列)
媳友。
bind
函數(shù)接受一個可調(diào)用對象,生成一個新的可調(diào)用對象來適配原對象。
函數(shù)原型
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
bind
函數(shù)接受一個逗號分割的參數(shù)列表args
,對應(yīng)給定函數(shù)對象fn
的參數(shù)页畦,返回一個新的函數(shù)對象。
參數(shù)列表args
中:
- 如果綁定到一個值焊唬,則調(diào)用返回的函數(shù)對象將始終使用該值作為參數(shù)
- 如果是一個形如
_n
的占位符,則調(diào)用返回的函數(shù)對象會轉(zhuǎn)發(fā)傳遞給調(diào)用的參數(shù)(該參數(shù)的順序號由占位符指定)
使用
#include <functional> //bind函數(shù) placeholders命名空間
int Plus(int x, int y) {
return x + y;
}
int PlusOne(int x) {
auto func = std::bind(Plus, std::placeholders::_1, 1);
return func(x);
}
int main()
{
std::cout << PlusOne(9) << std::endl; //結(jié)果 10
return 0;
}
注:示例代碼中的_1
即為形如_n
的占位符看靠,其定義在命名空間placeholders
中赶促,而此命名空間又定義在命名空間std
中
使用場景
根據(jù)bind
函數(shù)的特征,有以下幾個場景時可以使用bind
:
- 當(dāng)
bind
函數(shù)的參數(shù)列表綁定到一個值時挟炬,則調(diào)用返回的函數(shù)對象將始終使用該值作為參數(shù)鸥滨。所以bind
函數(shù)可以將一個函數(shù)的參數(shù)特例化,如上文的示例代碼 - 當(dāng)
bind
函數(shù)的參數(shù)列表是一個占位符時谤祖,調(diào)用返回的函數(shù)對象的參數(shù)順序號由占位符指定婿滓,所以bind
函數(shù)可以對調(diào)用函數(shù)對象的參數(shù)重新安排順序,例如:
using namespace std;
void output(int a, int b, int c) {
cout << a << " " << b << " " << c;
}
int main()
{
auto func = bind(output, placeholders::_2, placeholders::_1, placeholders::_3);
func(1, 2, 3); //結(jié)果 2 1 3
return 0;
}
- 與
std::function
配合粥喜,實現(xiàn)回調(diào)函數(shù)凸主。具體見文章C++ std::function,這里不再贅述额湘。
進(jìn)一步討論
bind
函數(shù)中非占位符的參數(shù)卿吐,將會以值拷貝的方式傳遞給返回的可調(diào)用對象中,所以直接使用bind
锋华,無法將參數(shù)以引用方式傳遞嗡官,或是綁定的參數(shù)類型無法拷貝。
我們需要使用ref
函數(shù)(函數(shù)ref
返回一個對象供置,包含給定的引用谨湘,此對象是可以拷貝的)來實現(xiàn)以引用方式傳遞參數(shù)绽快,或?qū)o法拷貝的參數(shù)類型可拷貝芥丧。
示例:
void add(int &x, int &y) {
x++;
y++;
}
int main()
{
int x = 1, y = 1;
auto func = bind(add, ref(x), y); //x以引用方式傳遞,y以值方式傳遞
func();
cout << x << " " << y; //結(jié)果 2 1
return 0;
}
相似的坊罢,cref
函數(shù)续担,用于生成一個保存const
引用的類。函數(shù)ref
與cref
也定義在頭文件functional
中活孩。
參考 《Primer C++ 第五版》