我知道函數是什麼以及何時使用它們與stl算法。但不明白他怎麼這個主題中的意思是:std :: function和std :: bind:它們是什麼以及它們何時被使用?
任何一個可以解釋什麼std::bind
和std::function
是,何時應該使用它,對新手的一些例子嗎?
我知道函數是什麼以及何時使用它們與stl算法。但不明白他怎麼這個主題中的意思是:std :: function和std :: bind:它們是什麼以及它們何時被使用?
任何一個可以解釋什麼std::bind
和std::function
是,何時應該使用它,對新手的一些例子嗎?
std::bind
用於partial function application。
也就是說,假設你有一個函數對象f
包含3個參數:
f(a,b,c);
你要定義一個新的函數對象,只需要兩個參數,如:
g(a,b) := f(a, 4, b);
g
是函數f
的「部分應用」:已經指定了中間參數,並且還剩下兩個參數。
您可以使用std::bind
獲得g
:
auto g = bind(f, _1, 4, _2);
這是比實際編寫一個函數子類做更加簡潔。
您鏈接到的文章中還有其他示例。當你需要傳遞一個函子給某個算法時,你通常會使用它。你有一個函數或仿函數,差不多做你想要的工作,但是比算法使用更多可配置(即有更多的參數)。所以你綁定參數的一些參數,並保留其餘的算法來填補:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
這裏,pow
有兩個參數,並能提高到任何力量,但我們關心的是提高到7
電源作爲一個偶爾使用不是局部的功能應用,bind
也可以重新排序參數的函數:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
我不建議使用它只是因爲你不喜歡的API,但它有例如潛在的實際用途,因爲:
not2(bind(less<T>, _2, _1));
是低於或相等的功能(假設總訂單,等等等等)。這個例子通常不是必須的,因爲已經有一個std::less_equal
(它使用<=
運算符而不是<
,所以如果它們不一致,那麼你可能需要這個,你可能還需要訪問類的作者cluestick)。不過,如果您使用的是功能性編程風格,則會出現這種轉變。
std :: bind在包含boost綁定的提案之後被投票到庫中,主要是部分函數專門化,其中 - 您可以修復幾個參數並在飛行中更改其他參數。現在,這是用C++編寫lambda表達式的庫方式。正如Steve Jessop回答的那樣
既然C++ 11支持lambda函數,那麼我不會再感到有任何使用std :: bind的誘惑。我寧願使用具有語言特徵的庫裏奇(部分專業化)而不是庫特徵。
std :: function對象是多態函數。基本思想是能夠互換地引用所有可調用的對象。
我想指出你這兩個環節進一步的細節:
lambda函數在C++ 11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
調用實體在C++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
沒有lambda表達式的'std :: bind'永遠不會存在 - 這兩個特性都是在C++ 11中引入的。我們確實有'bind1st'和'bind2nd',它們是C++ 11 bind的消毒版本。 –
我用它很長一段時間返回在C++中創建一個插件線程池;由於功能正在採取三個參數,你可以這樣寫
假設你的方法有簽名:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
要創建一個函數對象綁定三個參數,你可以做這樣的
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
現在,爲了綁定參數,我們必須編寫一個綁定器函數。所以,這裏有雲:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
而且,一個輔助函數使用binder3類 - bind3:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
,在這裏我們如何調用它
F3 f3 = PluginThreadPool::bind3(PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23);
注:F3 ();將調用方法task1-> ThreeParameterTask(21,22,23);
更多血淋淋的細節 - >http://www.codeproject.com/Articles/26078/A-C-Plug-in-ThreadPool-Design
一個主要使用std ::函數和std ::綁定的是安全的函數指針。網上有大量文章解釋了函數指針在C/C++中的用處。例如,它們對於實現回調機制很有用。也就是說,你有一些函數需要很長時間來執行,但你不想等待它返回,那麼你可以在單獨的線程上運行該函數,並給它一個函數指針,它會在它完成後回調它。
下面是如何使用此一個示例代碼:
class MyClass {
private:
//just shorthand to avoid long typing
typedef std::function<void (float result)> CallbackType;
//this function takes long time
void longRunningFunction(CallbackType callback)
{
//do some long running task
//...
//callback to return result
callback(result);
}
//this function gets called by longRunningFunction after its done
void afterCompleteCallback(float result)
{
std::cout << result;
}
public:
int longRunningFunctionAsync()
{
//create callback - this equivalent of safe function pointer
auto callback = std::bind(&MyClass::afterCompleteCallback,
this, std::placeholders::_1);
//normally you want to start below function on seprate thread,
//but for illustration we will just do simple call
longRunningFunction(callback);
}
};
也很方便於回調成員函數:'MyThread的升壓= ::螺紋(升壓::綁定(&MyClass的:: threadMain,此))' – rlduffy
好的解釋綁定。但是'std :: function'呢? – RedX
你的'pow'例子不能編譯。由於'pow'是一個重載函數,你必須手動指定哪個超載。綁定不能讓它由函數的調用者推導出來。例如。 'std :: transform(vec.begin(),vec.end(),out.begin(),std :: bind((double(*)(double,int))std :: pow,_1,7)) ;' –