यह एक अवतरण संदर्भ (मानक प्रस्ताव डॉक्टर) की घोषणा करता है ।
यहाँ संदर्भों का परिचय दिया गया है ।
यहाँ Microsoft के मानक लाइब्रेरी डेवलपर्स में से एक के संदर्भ में शानदार नज़र है ।
चेतावनी: MSDN पर लिंक लेख ("Rvalue References: C ++ 0x विशेषताएँ VC10 में, भाग 2") Rvalue संदर्भों के लिए एक बहुत ही स्पष्ट परिचय है, लेकिन Rvalue संदर्भों के बारे में बयान करता है जो एक बार ड्राफ्ट + 11 में सही थे। मानक, लेकिन अंतिम एक के लिए सच नहीं हैं! विशेष रूप से, यह विभिन्न बिंदुओं पर कहता है कि प्रतिद्वंद्वियों के संदर्भ अंतरालों को बांध सकते हैं, जो एक बार सच था, लेकिन बदल गया था (उदाहरण के लिए; int && rrx = x; अब जीसीसी में संकलित नहीं) - drewbsbs Jul 13 '14 16:12 पर;
C ++ 03 सन्दर्भ (अब C ++ 11 में एक लवल्यू रेफरेंस कहा जाता है) के बीच सबसे बड़ा अंतर यह है कि यह एक अस्थाई की तरह एक रव्वा को बाँध सकता है, जिसमें कॉन्स्टेबल न हों। इस प्रकार, यह वाक्यविन्यास अब कानूनी है:
T&& r = T();
rvalue संदर्भ मुख्य रूप से निम्नलिखित के लिए प्रदान करते हैं:
शब्दार्थ को स्थानांतरित करें । एक मूव कंस्ट्रक्टर और मूव असाइनमेंट ऑपरेटर को अब परिभाषित किया जा सकता है जो सामान्य कॉन्स्टल-लैवल्यू रेफरेंस के बजाय एक रवैल्यू रेफरेंस लेता है। एक प्रतिलिपि की तरह एक चाल कार्य करता है, सिवाय इसके कि स्रोत को अपरिवर्तित रखने के लिए बाध्य नहीं है; वास्तव में, यह आमतौर पर स्रोत को इस तरह से संशोधित करता है कि अब यह स्थानांतरित संसाधनों का मालिक नहीं है। यह बाहरी प्रतियों को खत्म करने के लिए बहुत अच्छा है, खासकर मानक पुस्तकालय कार्यान्वयन में।
उदाहरण के लिए, एक प्रतिलिपि निर्माता इस तरह दिख सकता है:
foo(foo const& other)
{
this->length = other.length;
this->ptr = new int[other.length];
copy(other.ptr, other.ptr + other.length, this->ptr);
}
यदि यह निर्माता अस्थायी रूप से पारित किया गया था, तो प्रतिलिपि अनावश्यक होगी क्योंकि हम जानते हैं कि अस्थायी बस नष्ट हो जाएगी; अस्थायी पहले से आवंटित संसाधनों का उपयोग क्यों नहीं करते? C ++ 03 में, प्रतिलिपि को रोकने का कोई तरीका नहीं है क्योंकि हम यह निर्धारित नहीं कर सकते कि हम एक अस्थायी पारित किए गए थे। C ++ 11 में, हम एक चाल निर्माणकर्ता को अधिभारित कर सकते हैं:
foo(foo&& other)
{
this->length = other.length;
this->ptr = other.ptr;
other.length = 0;
other.ptr = nullptr;
}
यहां बड़े अंतर पर ध्यान दें: चाल निर्माणकर्ता वास्तव में अपने तर्क को संशोधित करता है। यह प्रभावी रूप से निर्माण की जा रही वस्तु में अस्थायी रूप से "स्थानांतरित" करेगा, जिससे अनावश्यक प्रतिलिपि समाप्त हो जाएगी।
चाल निर्माणकर्ता का उपयोग अस्थायी लोगों के लिए और गैर-कॉन्स्टल लैवल्यू संदर्भों के लिए किया जाएगा जो स्पष्ट रूप से std::move
फ़ंक्शन का उपयोग करके संदर्भ संदर्भों में परिवर्तित हो जाते हैं (यह सिर्फ रूपांतरण करता है)। निम्नलिखित कोड दोनों के लिए कदम निर्माता आह्वान f1
और f2
:
foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"
foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"
एकदम सही अग्रेषण । rvalue के संदर्भ हमें अस्थायी कार्यों के लिए ठीक से तर्क देने की अनुमति देते हैं। उदाहरण के लिए इस कारखाने समारोह:
template <typename T, typename A1>
std::unique_ptr<T> factory(A1& a1)
{
return std::unique_ptr<T>(new T(a1));
}
अगर हम कहते हैं factory<foo>(5)
, तो तर्क को घटा दिया जाएगा int&
, जो कि शाब्दिक 5 से नहीं बंधेगा, भले ही foo
निर्माता एक लेता हो int
। ठीक है, हम इसके बजाय उपयोग कर सकते हैं A1 const&
, लेकिन क्या होगा यदि foo
गैर-कॉन्स्टेंस संदर्भ द्वारा निर्माता तर्क लेता है? वास्तव में एक सामान्य कारखाने समारोह बनाने के लिए हम पर कारखाने ओवरलोड करने के लिए होता A1&
है और पर A1 const&
। यदि कारखाना 1 पैरामीटर प्रकार लेता है, तो यह ठीक हो सकता है, लेकिन प्रत्येक अतिरिक्त पैरामीटर प्रकार 2. द्वारा निर्धारित आवश्यक अधिभार को गुणा करेगा। यह बहुत जल्दी अप्राप्य है।
मानक लाइब्रेरी को किसी std::forward
फ़ंक्शन को परिभाषित करने की अनुमति देकर इस समस्या को ठीक करता है, जो कि रेवल्यू / रेवल्यू संदर्भों को ठीक से अग्रेषित कर सकता है। कैसे std::forward
काम करता है, इसके बारे में अधिक जानकारी के लिए , यह उत्कृष्ट उत्तर देखें ।
यह हमें कारखाने के कार्य को इस तरह परिभाषित करने में सक्षम बनाता है:
template <typename T, typename A1>
std::unique_ptr<T> factory(A1&& a1)
{
return std::unique_ptr<T>(new T(std::forward<A1>(a1)));
}
अब तर्क के तर्क / अंतराल-नेस को संरक्षित किया जाता है, जब उसे T
निर्माणकर्ता के पास भेज दिया जाता है । इसका मतलब है कि अगर फैक्ट्री को रिवाल्यू कहा जाता है, तो T
कंस्ट्रक्टर को रिवाल्यू कहा जाता है। अगर फैक्ट्री को लैवेल्यू कहा जाता है, तो T
कंस्ट्रक्टर को लैवेल्यू कहा जाता है। एक विशेष नियम के कारण सुधरे हुए कारखाने का कार्य काम करता है:
जब फंक्शन पैरामीटर टाइप उस प्रकार का होता है, T&&
जहां T
टेम्पलेट पैरामीटर होता है, और फ़ंक्शन तर्क प्रकार का एक अंतराल होता है A
, तो टाइप A&
का उपयोग टेम्पलेट तर्क कटौती के लिए किया जाता है।
इस प्रकार, हम कारखाने का उपयोग कर सकते हैं जैसे:
auto p1 = factory<foo>(foo()); // calls foo(foo&&)
auto p2 = factory<foo>(*p1); // calls foo(foo const&)
महत्वपूर्ण संदर्भ संदर्भ गुण :
- अधिभार संकल्प के लिए, लवलेव्स रेवल्यू संदर्भों के लिए बाध्यकारी पसंद करते हैं और रिवेल्यूज़ रैवल्यू संदर्भों के लिए बाइंडिंग पसंद करते हैं । इसलिए अस्थायी लोग कॉपी कंस्ट्रक्टर / असाइनमेंट ऑपरेटर के ऊपर मूव कंस्ट्रक्टर / मूव असाइनमेंट ऑपरेटर को इनवॉइस करना पसंद करते हैं।
- rvalue सन्दर्भ निहितार्थों से और अस्थायी तौर पर बंधे होंगे जो एक अंतर्निहित रूपांतरण का परिणाम हैं । यानी
float f = 0f; int&& i = f;
अच्छी तरह से बनता है क्योंकि फ्लोट का तात्पर्य अंतर से आंतरिक में होता है; संदर्भ एक अस्थायी होगा जो रूपांतरण का परिणाम है।
- नामित रूवेल्यू संदर्भ लैवल हैं। अनाम: अवतरण संदर्भ rvalues हैं। यह समझना महत्वपूर्ण है कि इसमें
std::move
कॉल क्यों आवश्यक है:foo&& r = foo(); foo f = std::move(r);