2010-09-15 16 views
28

नीचे विचार करें।क्या रावल्यू संदर्भ संदर्भों को लटकाने की अनुमति देते हैं?

#include <string> 
using std::string; 

string middle_name() { 
    return "Jaan"; 
} 

int main() 
{ 
    string&& danger = middle_name(); // ?! 
    return 0; 
} 

यह कुछ भी गणना नहीं करता, लेकिन यह त्रुटि के बिना संकलित करता है तथा कुछ है कि मैं संशय को दर्शाता है: danger एक झूलने संदर्भ है, है ना?

+2

मुझे पहेली है कि आप बाईं तरफ का उपयोग कर सकते हैं, जब यह उपयोगी होगा? –

+2

@ विक्टर: एक रावल्यू संदर्भ अस्थायी रूप से बाध्य हो सकता है और अभी भी संशोधित हो सकता है। जैसे 'int && variable_or_dummy = modified_var? चाल (var): int(); ' – Potatoswatter

+0

एक जिसे आप एक रावल्यू नाम देते हैं, यह मुख्य रूप से 'खतरे' में एक लालसा बन जाता है। rvalueness या lvalueness एक अभिव्यक्ति की एक संपत्ति है –

उत्तर

38

क्या रावल्यू संदर्भ संदर्भों को लटकाने की अनुमति देते हैं?

यदि आपका मतलब है "क्या यह खतरनाक रावल संदर्भों को बनाना संभव है" तो उत्तर हाँ है। आपका उदाहरण, हालांकि,

string middle_name() { 
    return "Jaan"; 
} 

int main() 
{ 
    string&& nodanger = middle_name(); // OK. 
    // The life-time of the temporary is extended 
    // to the life-time of the reference. 
    return 0; 
} 

बिल्कुल ठीक है। एक ही नियम यहां लागू होता है जो this example (हर्ब सटर द्वारा लेख) को सुरक्षित बनाता है। यदि आप शुद्ध रावल्यू के साथ संदर्भ प्रारंभ करते हैं, तो टेम्पोरी ऑब्जेक्ट का जीवनकाल संदर्भ के जीवनकाल तक बढ़ा दिया जाता है। हालांकि, आप अभी भी लटकने वाले संदर्भों का उत्पादन कर सकते हैं। उदाहरण के लिए, यह अब और सुरक्षित नहीं है:

int main() 
{ 
    string&& danger = std::move(middle_name()); // dangling reference ! 
    return 0; 
} 

क्योंकि std::move रिटर्न एक string&& (जो है एक शुद्ध rvalue नहीं) नियम यह है कि के अस्थायी जीवन समय लागू नहीं होता फैली हुई है। यहां, std::move एक तथाकथित xvalue देता है। एक xvalue सिर्फ एक अज्ञात रैल्यू संदर्भ है। जैसे कि यह कुछ भी संदर्भित कर सकता है और यह अनुमान लगाने के लिए मूल रूप से असंभव है कि एक लौटा संदर्भ संदर्भ के कार्यान्वयन को देखे बिना संदर्भित करता है।

+4

अच्छी तरह से इरादा 'चाल' के उत्कृष्ट उदाहरण बहुत चले गए! – Potatoswatter

+0

@ सेलिबिटज़ 'स्ट्रिंग और खतरे = std :: move (middle_name()) होगा; ठीक है? – KitsuneYMG

+1

@kts: नहीं। यह संकलित भी नहीं होगा क्योंकि आप एक रावल्यू अभिव्यक्ति के साथ एक गैर-कॉन्स लैवल्यू संदर्भ प्रारंभ नहीं कर सकते हैं। यदि आप 'स्ट्रिंग कॉन्स और खतरे = move (middle_name()) लिखते हैं, तो यह या तो काम नहीं करेगा। यह संकलित होगा लेकिन 'खतरे' एक खतरनाक संदर्भ होगा। – sellibitze

3

danger एक खतरनाक संदर्भ है, है ना?

नहीं की तुलना में अगर आप एक const & का इस्तेमाल किया था किसी भी अधिक: danger rvalue के स्वामित्व लेता है।

14

रावल संदर्भ संदर्भों से बंधे हैं। एक रैल्यू या तो प्रावधान या xvalue [explanation] है। पूर्व के लिए बाध्यकारी कभी भी एक हानिकारक संदर्भ नहीं बनाता है, जो बाद की शक्ति के लिए बाध्यकारी हो सकता है। यही कारण है कि एक समारोह के रिटर्न प्रकार के रूप में T&& चुनना आम तौर पर एक बुरा विचार है। std::move इस नियम के लिए अपवाद है।

T& lvalue(); 
T prvalue(); 
T&& xvalue(); 

T&& does_not_compile = lvalue(); 
T&& well_behaved = prvalue(); 
T&& problematic = xvalue(); 
+0

+1 आप सही हैं, यह अंगूठे का एक अच्छा नियम है न कि उन कार्यों को लिखना जो रावल संदर्भों को वापस करते हैं। std :: move और std :: आगे स्पष्ट अपवाद हैं। – sellibitze

संबंधित मुद्दे