2013-04-12 4 views
6

की गलत अग्रेषण मैं नए जोड़े गए रावल्यू रिफर्न्स (बनाम2012 एक्सप्रेस में) के साथ प्रयोग कर रहा था।रैवल्यू संदर्भ

मुझे कुछ समझ में नहीं आता है। नीचे दिए गए कोड को देखते हुए (इसमें से अधिकांश सी ++ मानक से लिया गया है जहां std :: आगे समझाया गया है)।

struct A 
{ 
    A(int& i, const float& j): 
     m_i(i), 
     m_j(j){} 

    int& m_i; 
    const float& m_j; 
}; 

template<class T, class A1, class A2> 
T* factory(A1&& a1, A2&& a2) 
{ 
    return new T(a1, a2); 
} 

void test() 
{ 

    A* a1 = factory<A>(1, 1.2f); 

    //How does this work ?   
    a1->m_i = 2; 
} 

मुझे समझ में नहीं आता कि m_i कहां से बंधे हैं।

मैं मूल रूप से, एक rvalue संदर्भ (& & &) के लिए एक lvalue संदर्भ होगा द्वारा रेफरी नियम टूट हो जाता है (&) सिर्फ एक सादे lvalue रेफरी। लेकिन क्या संदर्भ है?

उत्तर

10

उपयोग करने के लिए मुझे समझ नहीं आता जहां से आबद्ध m_i है की जरूरत है।

m_iA के निर्माता का तर्क है। A के कन्स्ट्रक्टर का तर्क क्या है?

इस मामले में, factory के बाद से करता नहीं आगे A (यानी यह std::forward<>() उपयोग नहीं करता है) करने के लिए अपने तर्क, तो क्या A के लिए पारित किया जा रहा है एक lvalue है। ऐसा इसलिए है क्योंकि a1नाम है, और नामित वस्तुएं हैं।

प्रकार a1 की कि क्या a1 निर्धारित करने के लिए प्रासंगिक नहीं है एक lvalue या एक rvalue है। तो भले ही a1 टाइपint (int&&) को rvalue-संदर्भ में है, के रूप में अपने कार्यक्रम में मामला है, पैरामीटर a1 अपने आप में एक नामित वस्तु है, और इसलिए यह एक lvalue है।

इसका मतलब यह है, m_i के बाद से int को lvalue-संदर्भ टाइप करें, कि m_ifactory की (lvalue) पैरामीटर a1, जो जब factory() रिटर्न नष्ट हो जाएगा करने के लिए बाध्य किया जा सकता है (और वास्तव में ही है) है। दूसरे शब्दों में, आपको एक खतरनाक संदर्भ के साथ छोड़ दिया गया है।

इसे अस्वीकार करने का प्रयास (जैसा कि आप बाद में अपने कार्यक्रम में करते हैं) सम्मन अपरिभाषित व्यवहार

template<class T, class A1, class A2> 
T* factory(A1&& a1, A2&& a2) 
{ 
    return new T(std::forward<A1>(a1), std::forward<A2>(a2)); 
} 

यह एक संकलक त्रुटि के कारण होता है, क्योंकि std::forward<>() की मशीनरी सुनिश्चित करें कि lvalues ​​lvalues ​​रहने देते थे और:

हालांकि, अगर आपकी factory() समारोह था अपने तर्कों A के निर्माता के पास भेज और राजस्व rvalues ​​रहते हैं। एक राजस्व के लिए एक लालसा संदर्भ को बांधने का प्रयास अवैध है, और इसलिए A के निर्माता को कॉल विफल हो गया होगा।

+0

स्कॉट मेयर्स ने इंगित किया कि, एक सार्वभौमिक संदर्भ ('t ​​&& 'टाइप-प्रत्याशित' टी' के साथ) का उपयोग किसी भी 'std :: forward' या' std :: move' के बिना कम से कम संदिग्ध है । अब मैं स्पष्ट रूप से देख सकता हूं क्यों। –

3

लेकिन क्या संदर्भ है?

यह एक अनिर्धारित व्यवहार है। जैसा कि आपने सही अनुमान लगाया है, यह एक अस्थायी का संदर्भ है जिसे फंक्शन factory के ढेर में नष्ट कर दिया गया था। संकलन समय में इस तरह के मुद्दों को पकड़ने के लिए, आपको std::forward

template<class T, class A1, class A2> 
T* factory(A1&& a1, A2&& a2) 
{ 
    return new T(std::forward<A1>(a1), std::forward<A2>(a2)); 
} 
+0

'ए 1 और ए 1 'को एक rvalue_ref की आवश्यकता नहीं है, यह एक lvalue_ref भी स्वीकार कर सकता है क्योंकि वे टेम्पलेट द्वारा टाइप किए जाते हैं। इसलिए जब भी टेम्पलेट द्वारा एक प्रकार का कटौती किया जाता है और आप फ़ंक्शन कॉल के संदर्भ के प्रकार को संरक्षित नहीं करना चाहते हैं, तो आपको 'std :: forward' – balki

+0

अप्स का उपयोग करना होगा .... मैंने गलती से अपना कॉमेंट हटा दिया है। धन्यवाद। पुरानी टिप्पणी: क्या मुझे हमेशा ldue संदर्भों के साथ std :: आगे का उपयोग करने की आवश्यकता है?) – Alex

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