क्या मैं (वास्तव में आसान नहीं स्रोत का एक सरसरी पढ़ने और कुछ प्रयोगों से आंकना) प्राप्त कर सकते हैं यह क्लोन वस्तु हर बार की प्रतिलिपि बनाएगा से। यह कार्यद्वारा इसे तर्क के मामले में अनावश्यक हो सकता है, लेकिन सामान्य रूप से ऑब्जेक्ट को फ़ंक्शन द्वारा उत्परिवर्तित किया जा सकता है। यदि वस्तु कॉपी करने के लिए महंगा है, यह समझ बनाने के संदर्भ (boost::ref
या boost::cref
दिमाग में आते हैं) या द्वारा यह कब्जा करने के लिए नहीं होता, यदि मूल वस्तु मंगलाचरण के बिंदु पर मौजूद नहीं है, एक boost::shared_ptr
को पकड़ने और एक एडाप्टर बारे में विधि, जो smartpointer unpacks और someFunction
पर कॉल करता है?
संपादित करें: प्रयोग से न केवल boost::function
की प्रतिलिपि बनाई गई है, लेकिन यह boost::bind
के अंदर कई बार प्रतिलिपि बनायेगी।
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;
}
जिसके परिणामस्वरूप उत्पादन पीछा किया जाता है के रूप में: मैं जीसीसी 4.6 और -O2 (और -std = C++ 0x) के साथ MinGW 32 के अंतर्गत निम्नलिखित कोड बढ़ावा 1.45 का उपयोग कर का उपयोग कर परीक्षण किया
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
इसलिए कॉपी कन्स्ट्रक्टर को बाईंडिंग और एफ 1 के लिए असाइनमेंट के लिए एक बार और 11 बार बनाने के लिए बुलाया गया था। चूंकि पहली वस्तु स्टैक पर बनाई गई है और प्रतियों के पते उस के बहुत करीब हैं और थोड़ा बढ़ रहे हैं, ऐसा लगता है कि बाध्यकारी प्रक्रिया बहुत से कार्यों से गुज़रती है, जो संकलक इस मामले में इनलाइन नहीं करता है और प्रत्येक ऑब्जेक्ट को मूल्य के साथ पास करें। बस 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 :: समारोह/std :: समारोह के साथ) का बेहतर प्रदर्शन (कोड मूल रूप से पहले 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
या तो आंतरिक आमंत्रण के लिए कॉन्स्ट रेफ द्वारा गुजरता है, या इस तरह से लिखा जाता है कि जीसीसी इनलाइनर के लिए कुछ अनुकूल है और अनावश्यक प्रतिलिपि बनाने वालों को खत्म करने के लिए अधिक अनुकूल है। tr1::bind
तब भी boost::bind
को बेहतर अनुकूलित किया जाता है, लेकिन अभी भी इष्टतम से दूर है।
बेशक हमेशा इस तरह के परीक्षणों के साथ वाईएमएमवी विभिन्न संकलन झंडे/कंपाइलर्स
से बाहर आता है जब
g(const a &)
के माध्यम सेff()
याff2()
@ क्रिस: ठीक है, तो मेरा परीक्षण जानना अच्छा नहीं था। तो अगर कोई सी ++ 11 का उपयोग कर सकता है तो ऐसा लगता है कि std :: बाइंड एक बहुत ही मार्जिन से जाने का तरीका है (हालांकि व्यक्तिगत रूप से मैं इसके बजाय लैम्बडा का उपयोग करता हूं)। – Grizzly