दिलचस्प पोस्ट
JPA और सीतनिद्रा में होना का उपयोग करते समय कैसे बराबर और हैश कोड लागू किया जाना चाहिए जावा में बाइनरी प्रारूप में एक पूर्णांक को प्रिंट करें कैसे रद्द करें / रोकें jQuery के AJAX अनुरोध? पायथन फ़ंक्शन ओवरलोडिंग सी # (.नेट 2.0) में विंडोज के लिए इंटरप्रोसेस कम्यूनिकेशन डायनामिक रूप से iframe src सेट करें एक सरणी से यादृच्छिक तत्व चुनें स्थानीय या अस्थायी चर के संदर्भ लौटाना क्या लूप के लिए और प्रत्येक लूप के लिए एक अंतर है? कैसे प्रोग्राम की मात्रा को सिस्टम मात्रा निर्धारित करें? जावास्क्रिप्ट में पाठ फ़ाइल कैसे पढ़ा जाए पासवर्ड हैश के लिए गैर यादृच्छिक नमक यूनिकोडडेकोड एर्रर: 'मोरैप' कोडेक स्थिति में बाइट एक्स को डीकोड नहीं कर सकता Y: वर्ण मैप को <undefined> अस्पष्ट पारदर्शी पृष्ठभूमि प्रभाव बनाएँ तिथि (डेटस्ट्रिंग) और नए दिनांक (डेटस्ट्रिंग) के बीच अंतर

सी ++ 11 रिटर्न मूल्य अनुकूलन या कदम?

मुझे समझ में नहीं आ रहा है कि मुझे std::move उपयोग क्यों करना चाहिए और जब मुझे संकलक अनुकूलन देना चाहिए … उदाहरण के लिए:

 using SerialBuffer = vector< unsigned char >; // let compiler optimize it SerialBuffer read( size_t size ) const { SerialBuffer buffer( size ); read( begin( buffer ), end( buffer ) ); // Return Value Optimization return buffer; } // explicit move SerialBuffer read( size_t size ) const { SerialBuffer buffer( size ); read( begin( buffer ), end( buffer ) ); return move( buffer ); } 

मुझे किस का उपयोग करना चाहिए?

वेब के समाधान से एकत्रित समाधान "सी ++ 11 रिटर्न मूल्य अनुकूलन या कदम?"

विशेष रूप से पहली विधि का प्रयोग करें:

 Foo f() { Foo result; mangle(result); return result; } 

यह पहले ही चालन निर्माता के उपयोग की अनुमति देगा, अगर कोई उपलब्ध हो। वास्तव में, स्थानीय वैरिएबल return स्टेटमेंट में एक रैवल्यू रेफरेंस के साथ बाध्य हो सकता है, जब प्रतिलिपि की अनुमति दी जाती है।

आपका दूसरा संस्करण प्रतिलिपि elision सक्रिय रूप से प्रतिबंधित करता है पहला संस्करण सार्वभौमिक रूप से बेहतर है।

सभी वापसी मूल्य या तो पहले से ही moved या ऑप्टिमाइज़ किए गए हैं, इसलिए रिटर्न वैल्यू के साथ स्पष्ट रूप से आगे बढ़ने की कोई आवश्यकता नहीं है।

कम्पाइलर को स्वचालित रूप से वापसी मूल्य (कॉपी को ऑप्टिमाइज़ करने) करने की अनुमति है, और यहां तक ​​कि इस कदम को अनुकूलित भी करें!

N3337 मानक ड्राफ्ट (सी +11 11) की धारा 12.8 :

जब कुछ मानदंडों को पूरा किया जाता है, तो एक कार्यान्वयन को किसी वस्तु के प्रतिलिपि / स्थानांतरित निर्माण को छोड़ने की अनुमति दी जाती है, भले ही वस्तु के लिए प्रतिलिपि / चालनकर्ता और / या नाशक के पास दुष्प्रभाव हो। ऐसे मामलों में, कार्यान्वयन छोड़े गए प्रतिलिपि / स्थानांतरित ऑपरेशन के स्रोत और लक्ष्य को उसी वस्तु का संदर्भ देने के दो अलग-अलग तरीकों के साथ व्यवहार करता है, और उस वस्तु का विनाश उस समय के बाद होता है जब दो ऑब्जेक्ट होता। ऑप्टिमाइज़ेशन के बिना नष्ट कर दिया गया है। प्रतिलिपि एलिसन कहा जाता है, प्रतिलिपि / स्थानांतरित ऑपरेशन की इस ऐलिस को निम्नलिखित परिस्थितियों में अनुमति दी जाती है (जो कई प्रतियों को समाप्त करने के लिए जोड़ा जा सकता है):

[…]

उदाहरण :

 class Thing { public: Thing(); ~Thing(); Thing(const Thing&); }; Thing f() { Thing t; return t; } Thing t2 = f(); 

क्लास Thing के प्रतिलिपि कन्स्ट्रक्टर को दो कॉल्स को खत्म करने के लिए एलिमेंशन के मानदंड को जोड़ा जा सकता है: स्थानीय स्वचालित ऑब्जेक्ट t को प्रतिलिपि बनाने के लिए अस्थायी ऑब्जेक्ट में फ़ंक्शन की रिटर्न वैल्यू f() और ऑब्जेक्ट में उस अस्थायी वस्तु की प्रतिलिपि t2 प्रभावी रूप से, स्थानीय ऑब्जेक्ट t का निर्माण वैश्विक ऑब्जेक्ट t को सीधे आरंभ करने के रूप में देखा जा सकता है, और उस ऑब्जेक्ट का विनाश कार्यक्रम निकास पर होगा। Thing लिए एक चालन निर्माता जोड़ने से एक ही प्रभाव पड़ता है, लेकिन यह अस्थायी ऑब्जेक्ट से टी 2 के चलते निर्माण होता है जो कि लुप्त हो गया है। – अंत उदाहरण ]

जब एक प्रतिलिपि ऑपरेशन के elision के मानदंड मिले हैं या मिलेगा तथ्य यह है कि स्रोत ऑब्जेक्ट एक फ़ंक्शन पैरामीटर है, और प्रतिलिपि करने के लिए ऑब्जेक्ट एक lvalue, प्रतिलिपि के लिए कन्स्ट्रक्टर का चयन करने के लिए अधिभार संकल्प द्वारा नामित है पहले प्रदर्शन के रूप में अगर वस्तु एक rvalue द्वारा निर्दिष्ट कर रहे थे। अगर अधिभार संकल्प विफल हो जाता है, या अगर चयनित कन्स्ट्रक्टर का पहला पैरामीटर ऑब्जेक्ट प्रकार (संभवतः सीवी-योग्य) के लिए एक रैवल्यू संदर्भ नहीं होता है, तो ओवरलोड रिज़ॉल्यूशन फिर से किया जाता है, ऑब्जेक्ट को लावल्यू के रूप में देखते हुए।

यह काफी सरल है

return buffer;

यदि आप ऐसा करते हैं, तो एनआरवीओ होगा या नहीं। यदि ऐसा नहीं होता है तो buffer से स्थानांतरित किया जाएगा

return std::move( buffer );

यदि आप ऐसा करते हैं, तो एनवीआरओ नहीं होगा, और buffer से स्थानांतरित किया जाएगा।

तो यहां std::move का उपयोग करके हासिल करने के लिए कुछ भी नहीं है, और हारना बहुत अधिक है

इस नियम में एक अपवाद है:

 Buffer read(Buffer&& buffer) { //... return std::move( buffer ); } 

यदि buffer एक रैवल्यू संदर्भ है, तो आपको std::move उपयोग करना चाहिए इसका कारण यह है कि संदर्भ एनआरवीओ के लिए योग्य नहीं हैं, इसलिए बिना स्टड std::move परिणामस्वरूप एक प्रतिलिपि एक लावलू से होगी।

यह नियम का सिर्फ एक उदाहरण है, "हमेशा रैवल्यू संदर्भों को forward और सार्वभौमिक संदर्भों को forward ", जो नियम पर "पूर्व वापसी मूल्य" कभी नहीं लेते हैं।

यदि आप एक स्थानीय चर लौट रहे हैं, तो move() उपयोग न करें यह संकलक को एनआरवीओ का उपयोग करने की अनुमति देगा, और असफल होने पर, संकलक को अभी भी एक चाल (स्थानीय return एक return स्टेटमेंट के भीतर R-values ​​बनने के लिए) की अनुमति दी जाएगी। उस संदर्भ में move() का उपयोग केवल एनआरवीओ को बाधित करेगा और एक चाल का उपयोग करने के लिए संकलक को मजबूर करेगा (या यदि प्रतिलिपि अनुपलब्ध है तो प्रतिलिपि)। यदि आप किसी स्थानीय चर के अलावा कुछ और लौट रहे हैं, तो एनआरवीओ किसी भी विकल्प का विकल्प नहीं है और आपको move() उपयोग करना चाहिए move() यदि (और केवल तभी) यदि आप ऑब्जेक्ट को पालिच करना चाहते हैं