नोट: यह उत्तर केवल c ++ 11 पर लागू होता है। "सी / सी ++" जैसी कोई चीज नहीं है, वे अलग-अलग भाषाएं हैं।
नहीं, मूल्य द्वारा किसी स्थानीय वस्तु को वापस करने में कोई खतरा नहीं है, और ऐसा करने के लिए सिफारिश की जाती है। हालांकि, मुझे लगता है कि एक महत्वपूर्ण बिंदु है जो यहां सभी उत्तरों से गायब है। कई अन्य लोगों ने कहा है कि संरचना को या तो कॉपी किया जा रहा है या सीधे आरवीओ का उपयोग करके रखा गया है। हालाँकि, यह पूरी तरह सही नहीं है। मैं यह समझाने की कोशिश करूंगा कि स्थानीय वस्तु वापस करते समय कौन सी चीजें हो सकती हैं।
शब्दार्थ को स्थानांतरित करें
सी ++ 11 के बाद से, हमारे पास संदर्भ संदर्भ हैं जो अस्थायी वस्तुओं के संदर्भ हैं जो सुरक्षित रूप से चोरी हो सकते हैं। एक उदाहरण के रूप में, std :: वेक्टर में एक मूव कंस्ट्रक्टर है और साथ ही एक मूव असाइनमेंट ऑपरेटर भी है। इन दोनों में निरंतर जटिलता होती है और बस पॉइंटर को वेक्टर के डेटा से कॉपी किया जाता है। मैं यहाँ कदम शब्दार्थ के बारे में अधिक विस्तार में नहीं जाऊँगा।
क्योंकि किसी फ़ंक्शन के भीतर स्थानीय रूप से बनाई गई वस्तु अस्थायी होती है और फ़ंक्शन के वापस आने पर स्कोप से बाहर चली जाती है, लौटी हुई वस्तु को कभी भी c ++ 11 के साथ कॉपी नहीं किया जाता है। इस कदम के निर्माता को लौटाए जा रहे ऑब्जेक्ट (या बाद में समझाया गया) पर बुलाया जा रहा है। इसका मतलब यह है कि यदि आप किसी ऑब्जेक्ट को एक महंगी कॉपी कंस्ट्रक्टर के साथ लेकिन सस्ती चाल वाले कंस्ट्रक्टर के साथ वापस करना चाहते थे, तो एक बड़े वेक्टर की तरह, केवल डेटा का स्वामित्व स्थानीय ऑब्जेक्ट से लौटी हुई वस्तु में स्थानांतरित किया जाता है - जो सस्ता है।
ध्यान दें कि आपके विशिष्ट उदाहरण में, ऑब्जेक्ट को कॉपी करने और स्थानांतरित करने में कोई अंतर नहीं है। एक ही संचालन में आपकी संरचना के डिफ़ॉल्ट मूवमेंट और कॉपी कंस्ट्रक्टर्स; दो पूर्णांकों की प्रतिलिपि बनाना। हालांकि, यह किसी भी अन्य समाधान की तुलना में कम से कम तेज है क्योंकि पूरी संरचना 64-बिट सीपीयू रजिस्टर में फिट होती है (मुझे गलत होने पर सही करें, मुझे बहुत सीपीयू रजिस्टर नहीं पता है)।
आरवीओ और एनआरवीओ
आरवीओ का मतलब रिटर्न वैल्यू ऑप्टिमाइजेशन है और यह उन कुछ ऑप्टिमाइज़ेशन में से एक है जो कंपाइलर करते हैं जिनके साइड इफेक्ट हो सकते हैं। चूंकि सी ++ 17, आरवीओ की आवश्यकता है। किसी अनाम वस्तु को वापस करते समय, इसका निर्माण सीधे उस स्थान पर किया जाता है, जहाँ कॉलर लौटाया गया मान प्रदान करता है। न तो कॉपी कंस्ट्रक्टर और न ही मूव कंस्ट्रक्टर को बुलाया जाता है। आरवीओ के बिना, अनाम वस्तु को पहले स्थानीय रूप से निर्मित किया जाएगा, फिर लौटे पते में निर्मित किया जाएगा, फिर स्थानीय अनाम वस्तु को नष्ट कर दिया जाएगा।
उदाहरण जहां आरवीओ आवश्यक है (c ++ 17) या संभावना (c ++ 17 से पहले):
auto function(int a, int b) -> MyStruct {
return MyStruct{a, b};
}
NRVO का अर्थ होता है नामांकित रिटर्न वैल्यू ऑप्टिमाइज़ेशन और यह आरवीओ की तरह ही होता है, सिवाय इसके कि यह किसी नामित ऑब्जेक्ट के लिए किया जाता है जिसे फ़ंक्शन कहते हैं। यह अभी भी मानक (सी ++ 20) द्वारा गारंटी नहीं है, लेकिन कई कंपाइलर अभी भी करते हैं। ध्यान दें कि नामित स्थानीय वस्तुओं के साथ भी, जब वे लौटे तो सबसे खराब स्थिति में हैं।
निष्कर्ष
एकमात्र मामला जहां आपको मूल्य पर वापस नहीं लौटने पर विचार करना चाहिए, जब आपके पास एक नामित, बहुत बड़ा (जैसा कि उसके स्टैक आकार में) ऑब्जेक्ट है। ऐसा इसलिए है क्योंकि NRVO की अभी गारंटी नहीं है (c ++ 20 के रूप में) और यहां तक कि ऑब्जेक्ट को हिलाना भी धीमा होगा। मेरी सिफारिश, और सीपीपी कोर दिशानिर्देशों में सिफारिश हमेशा मूल्य द्वारा वस्तुओं को वापस करने के लिए पसंद करती है (यदि कई रिटर्न मान, संरचना (या टपल) का उपयोग करें), जहां एकमात्र अपवाद तब होता है जब ऑब्जेक्ट को स्थानांतरित करना महंगा होता है। उस स्थिति में, एक नॉन-कास्ट संदर्भ पैरामीटर का उपयोग करें।
यह एक संसाधन को वापस करने के लिए एक अच्छा विचार नहीं है जिसे मैन्युअल रूप से c ++ में फ़ंक्शन से जारी किया जाना है। कभी मत करो। कम से कम एक std :: unique_ptr का उपयोग करें, या एक विध्वंसक के साथ अपना स्वयं का गैर-स्थानीय या स्थानीय ढांचा बनाएं जो अपने संसाधन ( RAII ) को जारी करता है और उसी का एक उदाहरण देता है। यह कदम कंस्ट्रक्टर को परिभाषित करने और असाइनमेंट ऑपरेटर को स्थानांतरित करने के लिए भी एक अच्छा विचार होगा यदि संसाधन का अपना चाल शब्दार्थ नहीं है (और प्रतिलिपि निर्माता / असाइनमेंट को हटा दें)।