從我可以找到(從不完全是簡單的源進行粗略的閱讀和一些實驗來看),它會在每次複製克隆的對象。這個函數可能沒有必要將它作爲const &的參數,但通常該對象可能會被該函數改變。如果該對象的拷貝成本很高,通過引用捕獲它是否有意義(想起boost::ref
或boost::cref
),或者如果原始對象在調用點不存在,則捕獲boost::shared_ptr
並編寫適配器方法,它解開智能指針並調用someFunction
?
編輯:從實驗開始,只要複製boost::function
,它不僅將複製該對象,而且它還將在boost::bind
內複製多次。我測試使用利用升壓1.45以下代碼的mingw下32用gcc 4.6和-O2(和-std = C++ 0X):
struct foo_bar {
std::vector<int> data; //possibly expensive to copy
foo_bar()
{ std::cout<<"default foo_bar "<<std::endl; }
foo_bar(const foo_bar& b):data(b.data)
{ std::cout<<"copy foo_bar "<<&b<<" to "<<this<<std::endl; }
foo_bar& operator=(const foo_bar& b) {
this->data = b.data;
std::cout<<"asign foo_bar "<<&b<<" to "<<this<<std::endl;
return *this;
}
~foo_bar(){}
};
void func(const foo_bar& bar) { std::cout<<"func"<<std::endl;}
int main(int, char*[]) {
foo_bar fb;
boost::function<void()> f1(boost::bind(func, fb));
std::cout<<"Bind finished"<<std::endl;
boost::function<void()> f2(f1);
std::cout<<"copy finished"<<std::endl;
f1();
f2();
return 0;
}
如隨後將得到的輸出:
default foo_bar
copy foo_bar 0x28ff00 to 0x28ff10
copy foo_bar 0x28ff10 to 0x28ff28
copy foo_bar 0x28ff28 to 0x28ff1c
copy foo_bar 0x28ff1c to 0x28ff34
copy foo_bar 0x28ff34 to 0x28fed4
copy foo_bar 0x28fed4 to 0x28fee4
copy foo_bar 0x28fee4 to 0x28fef4
copy foo_bar 0x28fef4 to 0x28fe14
copy foo_bar 0x28fe14 to 0x28fe24
copy foo_bar 0x28fe24 to 0x28fe34
copy foo_bar 0x28fe34 to 0x6a2c7c
Bind finished
copy foo_bar 0x6a2c7c to 0x6a2c94
copy finished
func
func
因此,調用copy構造函數創建f2一次和11次,以綁定和分配給f1。由於第一個對象是在堆棧上創建的,並且副本的地址非常接近並且略有增加,所以綁定過程似乎經歷了許多函數,編譯器在此情況下不內聯,並且每個函數通過值傳遞對象。只需使用boost::bind
,而不會有任何保存結果:
int main(int, char*[]) {
foo_bar fb;
boost::function<void()> f1(boost::bind(func, fb));
return 0;
}
default foo_bar
copy foo_bar 0x28ff00 to 0x28ff10
copy foo_bar 0x28ff10 to 0x28ff28
copy foo_bar 0x28ff28 to 0x28ff1c
copy foo_bar 0x28ff1c to 0x28ff34
copy foo_bar 0x28ff34 to 0x28fef4
所以五人副本只是對象綁定。因此,我總是會避免捕獲任何在代碼的任何遠程性能敏感部分中都至少降低每個值的複製成本的任何內容。相比之下GCCS std::tr1::bind
和std::bind
執行好得多(結合的std :: TR1 ::功能/性病::功能)(代碼基本上相同於第一testcode,只是代替boost::
與std::tr1::
分別std::
:
std::tr1::bind with std::tr1::function:
default foo_bar
copy foo_bar 0x28ff10 to 0x28ff28
copy foo_bar 0x28ff28 to 0x28ff34
copy foo_bar 0x28ff34 to 0x28ff04
copy foo_bar 0x28ff04 to 0x652c7c
Bind finished
copy foo_bar 0x652c7c to 0x652c94
copy finished
func
func
std::bind with std::function:
default foo_bar
copy foo_bar 0x28ff34 to 0x28ff28
copy foo_bar 0x28ff28 to 0x3c2c7c
Bind finished
copy foo_bar 0x3c2c7c to 0x3c2c94
copy finished
func
func
我認爲std::bind
要麼通過const ref來進行內部調用,要麼以更加友好的方式寫入gccs inliner以內聯一些並消除多餘的拷貝構造函數tr1::bind
仍然得到了更好的優化,然後boost::bind
,但仍然遠未達到最優。
當然,一直使用不同的編譯標誌/編譯器進行這樣的測試YMMV
叫我寫了一個測試程序,它看起來像存儲對象的拷貝構造函數每次拷貝函數對象時不會被調用。另外,boost :: bind調用拷貝構造函數11次! – Chris 2011-12-31 15:03:57
@克里斯:好吧,所以我的測試不是僥倖得知。所以,如果一個人可以使用C++ 11,看起來std :: bind是一種遠遠不夠的方式(儘管個人而言我只是使用lambdas代替)。 – Grizzly 2011-12-31 15:44:10