दिलचस्प पोस्ट
Photos.app से छवियों को अपलोड करने के लिए मोबाइल सफारी के लिए एक HTML5 वेब ऐप? 600851475143 में से सबसे बड़ी संख्या खोजना? दो भौगोलिक स्थानों के बीच दूरी की गणना करना आप 'अधिभार' क्यों नहीं कर सकते। ' सी ++ में ऑपरेटर? महीने का नाम से महीना नाम प्राप्त करें किसी मौजूदा प्रोजेक्ट को asp.NET MVC5 पहचान प्रमाणन जोड़ना अमेज़ॅन बादल फ़्रंट लेटेंसी तीन। जेएस प्रोजेक्टर और रे ऑब्जेक्ट्स मैं अपने XML फ़ाइल से BOM कैरेक्टर को कैसे निकालूं? Initializer_list vs 2013 में डबल हटाएं WINMAIN और मुख्य () सी ++ (विस्तारित) में अनछुए परिवर्तन का पता लगा रहा है iphone app पढ़ने एसएमएस XML दस्तावेज़ से निर्दिष्ट नोड मान प्राप्त करना RelativeLayout wrap_content के लिए पूर्ण स्क्रीन ले रहा है

सी ++ 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() यदि (और केवल तभी) यदि आप ऑब्जेक्ट को पालिच करना चाहते हैं