2012-12-26 34 views
7

एक समारोह फोन करने वाले के लिए दो मानों वापस जाने के लिए की जरूरत है। कार्यान्वित करने का सबसे अच्छा तरीका क्या है?RVO होगा जब std :: जोड़ी लौटने?

विकल्प 1:

pair<U,V> myfunc() 
{ 
... 
return make_pair(getU(),getV()); 
} 

pair<U,V> mypair = myfunc(); 

विकल्प 1.1:

// Same defn 
U u; V v; 
tie(u,v) = myfunc(); 

विकल्प 2:

void myfunc(U& u , V& v) 
{ 
u = getU(); v= getV(); 
} 

U u; V v; 
myfunc(u,v); 

मैं Option2 साथ पता है, वहाँ कोई प्रतियां/चाल हैं, लेकिन यह बदसूरत लग रहा है। विकल्प 1, 1.1 में कोई प्रतियां/चालें होंगी? आइए मान लें कि यू और वी दोनों बड़ी प्रतिलिपि हैं जो प्रतिलिपि/चालन संचालन का समर्थन करते हैं।

प्रश्न: यह सैद्धांतिक रूप से मानक के अनुसार किसी भी RVO/NRVO अनुकूलन के लिए संभव है? यदि हां, तो क्या जीसीसी या कोई अन्य कंपाइलर अभी तक कार्यान्वित है?

+1

मुझे 'std :: pair' के बारे में कुछ भी पता नहीं है जो आरवीओ/एनआरवीओ को रोक देगा। एक कॉपी कन्स्ट्रक्टर सहित परीक्षण करना आम तौर पर आसान होता है जो आपको बताता है कि एक प्रति कब होती है। –

+1

जी ++ RVO कि जोड़ी को कॉपी रोकता है, को लागू करता है लेकिन आप अभी भी यू की प्रति और वी जोड़ी में है। –

+0

मैं कुछ परीक्षण भाग गया, और मैंने पाया कि जी ++, जो एक तेज थी के साथ एक बहुत क्या पर इनलाइनिंग संभव हो गया था और यू और वी के लिए प्रति कंस्ट्रक्टर्स तुम सिर्फ प्रदर्शन के लिए देख रहे हैं की जटिलता निर्भर, मुझे लगता है तुम हूँ यह निर्धारित करने के लिए प्रोफाइल करना होगा कि सबसे तेज़ कौन सा है। –

उत्तर

8

RVO होगा जब std::pair लौटने?

हाँ, यह कर सकते हैं।

क्या यह होने की गारंटी है?

नहीं, यह नहीं है।


सी ++ 11 मानक: धारा 12.8/31:

जब कुछ मानदंडों को पूरा किया जाता है, एक कार्यान्वयन एक वर्ग वस्तु की कॉपी/कदम निर्माण छोड़ करने की अनुमति दी है, भले ही ऑब्जेक्ट के लिए प्रतिलिपि/चालक कन्स्ट्रक्टर और/या विनाशक के दुष्प्रभाव होते हैं।

कॉपी एलिजन एक गारंटीकृत सुविधा नहीं है। यह एक अनुकूलन compilers जब भी वे कर सकते हैंप्रदर्शन करने के लिए अनुमति दी जाती है। विशेष w.r.t std::pair कुछ भी नहीं है। यदि एक संकलक अनुकूलन अवसर का पता लगाने के लिए पर्याप्त है तो यह ऐसा करेगा। तो आपके सवाल का संकलक विशिष्ट है, लेकिन हाँ यही नियम किसी अन्य वर्ग के लिए के रूप में std::pair पर लागू होता है।

1

RVO या कॉपी इलिजन संकलक पर निर्भर है, इसलिए यदि आप RVO है और निर्माता सबसे अच्छा विकल्प संकेत का उपयोग करना है कॉपी करने के लिए कॉल से बचने के लिए चाहते हैं।

हमारे उत्पाद में हम उपयोग संकेत का उपयोग करें और बढ़ावा कंटेनर की प्रतिलिपि निर्माता से बचने के सूचक। और यह वास्तव में लगभग 10% के प्रदर्शन को बढ़ावा देता है।

आपके प्रश्न पर आ रहा है, विकल्प 1 यू और वी की कॉपी कन्स्ट्रक्टर को यू या वी वापस नहीं लौटाया जा रहा है, लेकिन std :: जोड़ी ऑब्जेक्ट लौटा रहा है, इसलिए इसकी प्रतिलिपि बनाने वाला कन्स्ट्रक्टर कहा जाएगा और अधिकांश कंपाइलर निश्चित रूप से उपयोग करेंगे आरवीओ से बचने के लिए यहां।

धन्यवाद नीरज राठी

4

जबकि RVO सी ++ 11 समारोह में, इसकी गारंटी नहीं है के रूप में आप इसे परिभाषित किया है मुझे विश्वास है चाहिए के लिए कदम-रिटर्न बहुत कम से कम, तो मैं नहीं बल्कि स्पष्ट परिभाषा छोड़ने का सुझाव यह warping उत्पादन-चर स्वीकार करने के लिए (जब तक आप उन्हें प्रयोग करने के लिए एक विशेष नीति है) की तुलना में।

इसके अलावा, भले इस उदाहरण उपयोग RVO किया था, make_pair की आपकी स्पष्ट उपयोग का मतलब है कि आप हमेशा कम से कम एक अतिरिक्त जोड़ी निर्माण और इस तरह एक कदम आपरेशन होगा। इसे एक ब्रेस-प्रारंभिक अभिव्यक्ति वापस करने के लिए बदलें:

return { getU(), getV() };