2011-01-16 16 views
8

इस कोड पर विचार करें,अंतर्निहित रूपांतरण: स्थिरांक संदर्भ बनाम गैर-स्थिरांक संदर्भ बनाम गैर-संदर्भ

struct A {}; 
struct B { B(const A&) {} }; 
void f(B) 
{ 
    cout << "f()"<<endl; 
} 
void g(A &a) 
{ 
    cout << "g()" <<endl; 
    f(a); //a is implicitly converted into B. 
} 
int main() 
{ 
    A a; 
    g(a); 
} 

यह compiles fine, ठीक चलाता है। लेकिन अगर मैं f(B) से f(B&) बदलता हूं, तो यह doesn't compile है। अगर मैं f(const B&) लिखता हूं, तो यह फिर से compiles fine, ठीक चलाता है। कारण और तर्क क्यों है?

सारांश:

void f(B);   //okay 
void f(B&);  //error 
void f(const B&); //okay 

मैं भाषा विनिर्देश से कारण हैं, तर्क और संदर्भ (रों) सुनने के लिए, इन मामलों में से प्रत्येक के लिए करना चाहते हैं। बेशक, फ़ंक्शन हस्ताक्षर स्वयं गलत नहीं हैं। इसके बजाय A स्पष्ट रूप से B और const B& में परिवर्तित हो गया है, लेकिन B& में नहीं है, और यह संकलन त्रुटि का कारण बनता है।

उत्तर

7

मैं कारणों से, तर्क और भाषा विनिर्देश

डिजाइन और सी ++ पर्याप्त विकास है से संदर्भ (रों) सुनने के लिए चाहते हैं?

मैं [टिप्पणी मेरे द्वारा एक गैर स्थिरांक संदर्भ एक गैर lvalue से प्रारंभ होने की अनुमति देकर एक गंभीर गलती की है, हालांकि, कि शब्दों अनिश्चित है!]। उदाहरण के लिए:

void incr(int& rr) { ++rr; } 

void g() 
{ 
    double ss = 1; 
    incr(ss); // note: double passed, int expected 
       // (fixed: error in release 2.0) 
} 
प्रकार में अंतर int& double तो एक अस्थायी पारित कर का उल्लेख नहीं कर सकते हैं की वजह से

एक intss के मूल्य से प्रारंभ धारण करने के लिए बनाया गया था। इस प्रकार, incr() अस्थायी संशोधित, और परिणाम कॉलिंग फ़ंक्शन [जोर मेरा] पर प्रतिबिंबित नहीं हुआ था।

इसके बारे में सोचो: कॉल-दर-संदर्भ के पूरे मुद्दे है कि ग्राहक चीजें हैं जो समारोह से बदल रहे हैं गुजरता है, और समारोह रिटर्न के बाद, ग्राहक परिवर्तन निरीक्षण करने के लिए सक्षम होना चाहिए।

+0

एक दिलचस्प बात: एआरएम में, प्राथमिक अभिव्यक्ति के लिए lvalueness का निर्धारण निम्नानुसार है: "परिणाम पहचानकर्ता है अगर परिणाम एक लालसा है।" .. "परिणाम सदस्य है यदि परिणाम है।" मैंने सोचा है कि बिल्ली का मतलब क्या होना चाहिए, क्योंकि यह भी परिभाषित करता है "एक लालच एक वस्तु या कार्य का जिक्र करते हुए एक अभिव्यक्ति है।" हम्म, शायद इसका मतलब यह है कि "परिणाम एक आभासी है यदि यह किसी ऑब्जेक्ट या फ़ंक्शन को संदर्भित करता है।" –

+0

यह अच्छा है। मुझे लगता है कि यह मेरे प्रश्न का बेहतर उत्तर देता है, क्योंकि यह कारण बताता है कि इसकी अनुमति क्यों नहीं है। मैं इसे अपने प्रश्न के उत्तर के रूप में स्वीकार कर रहा हूं। :-) – Nawaz

4

समस्या यह है कि बी से ऑब्जेक्ट में अंतर्निहित रूपांतरण एक रावल उत्पन्न करता है। गैर-कॉन्स संदर्भ केवल अंतराल से जुड़ सकते हैं।

यदि बी के पास डिफॉल्ट कन्स्ट्रक्टर था तो आप f(a) को f(B()) पर कॉल करते हैं तो आपको वही व्यवहार मिल जाएगा। -

litb क्या एक lvalue है के लिए एक महान उत्तर प्रदान करता है: Stack Overflow - often used seldom defined terms: lvalue

GotW #88: A Candidate For the “Most Important const”

Stack Overflow - How come a non-const reference cannot bind to a temporary object?

-

मानक के संदर्भ के साथ व्याख्या करने के लिए कैसे उन फ़ंक्शन कॉल विफल या सफल होने पर अत्यधिक लंबा होगा। महत्वपूर्ण बात यह है कि B& b = a; विफल रहता है जबकि const B& b = a; विफल नहीं होता है।

(मसौदा n1905 से)

एक संदर्भ टाइप करने के लिए "CV1 T1" के रूप में इस प्रकार "CV2 टी 2" की अभिव्यक्ति से आरंभ नहीं हो जाता:
- [ एक lvalue है और या तो संदर्भ है संगत या निहित रूप से एक संदर्भ संगत प्रकार के एक आभासी के लिए परिवर्तनीय ... ]
- अन्यथा, संदर्भ एक गैर-अस्थिर कॉन्स प्रकार (यानी, सीवी 1 होगा) होगा।

Here's एक मामला जहां कुछ संदर्भ संगत प्रकार के एक आभासी में परिवर्तनीय है।

+0

यह क्यों है कि @ नवाज के प्रश्न को 23 मिनट के लिए अनुत्तरित नहीं किया गया था, और जब मैंने इसका उत्तर दिया, तो आपने मेरे सामने 30 सेकंड का उत्तर दिया। वह जादू है! हाहा, +1। –

+0

@ क्रिस: कृपया प्रासंगिक संदर्भों को भी उद्धृत करें, ताकि मैं प्रासंगिक अवधारणाओं का पता लगा सकूं। – Nawaz

+3

कड़ाई से बोलते हुए, आप अंतराल या रावलू नहीं बना सकते हैं, क्योंकि मान-श्रेणी * अभिव्यक्ति * (संकलन समय) की विशेषता है, न कि * ऑब्जेक्ट * (रनटाइम)। – fredoverflow