2012-02-15 7 views
40

मैंने हर जगह पढ़ा है कि एक संदर्भ को तब शुरू किया जाना चाहिए और फिर से फिर से शुरू नहीं किया जा सकता है।क्या हम सी ++ में संदर्भ को पुन: असाइन कर सकते हैं?

मेरी समझ का परीक्षण करने के लिए, मैंने निम्नलिखित छोटे कार्यक्रम को लिखा है। ऐसा लगता है जैसे मैं वास्तव में एक संदर्भ को पुन: असाइन करने में सफल रहा हूं। क्या कोई मुझे बता सकता है कि वास्तव में मेरे कार्यक्रम में क्या चल रहा है?

#include <iostream> 
#include <stdio.h> 
#include <conio.h> 

using namespace std; 

int main() 
{ 
    int i = 5, j = 9; 

    int &ri = i; 
    cout << " ri is : " << ri <<"\n"; 

    i = 10; 
    cout << " ri is : " << ri << "\n"; 

    ri = j; // >>> Is this not reassigning the reference? <<< 
    cout << " ri is : " << ri <<"\n"; 

    getch(); 
    return 0; 
} 

कोड ठीक संकलित करता है तथा उत्पादन मैं उम्मीद के रूप में है:

ri is : 5 
ri is : 10 
ri is : 9 

उत्तर

42

ri = j; // >>> Is this not reassigning the reference? <<<

नहीं है, ri अभी भी i के लिए एक संदर्भ है - आप &ri और &i मुद्रण और देख वे एक ही पते हैं द्वारा यह साबित कर सकते हैं।

आपने जो किया है उसे i संदर्भ ri संशोधित किया गया है। i प्रिंट करें, और आप इसे देखेंगे।

इसके अलावा, यदि आप const int &cri = i; बनाते हैं तो यह आपको असाइन करने नहीं देगा।

+0

'const int और cri = i' क्यों अनुमति नहीं है? आप किस लाइन पर लिख नहीं सकते? मेरे लिए कारण संकलक किसी भी स्थान पर ऐसी लाइन डालने की अनुमति देता है। इसके अलावा, यह एक स्पष्ट और संक्षिप्त उत्तर है! – mercury0114

+0

मैंने यह नहीं कहा कि इसकी अनुमति नहीं है - जैसा कि आपने देखा है, एक गैर-कॉन्स्ट चर के लिए एक कॉन्स्ट रेफरी लेना ठीक है। मैंने कहा कि यह आपको उस_ को असाइन करने की अनुमति नहीं देता है, जिसका अर्थ है कि आप मूल चर को एक कॉन्स रेफरी के माध्यम से नहीं बदल सकते हैं, जैसे ओपी ने 'ri' के साथ किया था। – Useless

+0

ओह ठीक है, अब मैं देख रहा हूं कि आपका क्या मतलब है। – mercury0114

3

जब आप किसी संदर्भ के लिए कुछ आवंटित आप वास्तव में वस्तु संदर्भ के लिए बाध्य है के लिए मान असाइन। तो यह:

ri=j; 

i = j; 

के रूप में एक ही प्रभाव होता है क्योंकि rii करने के लिए बाध्य किया जाता है। तो ri पर कोई भी कार्रवाई i पर निष्पादित की गई है।

3

आप जब ri = j; क्रियान्वित संदर्भ फिर नियत नहीं कर रहे हैं। आप वास्तव में ji असाइन कर रहे हैं। लाइन के बाद i प्रिंट करने का प्रयास करें और आप देखेंगे कि i बदले गए मूल्य।

6

ऐसा लगता है जैसे मैं वास्तव में संदर्भ को पुन: असाइन करने में सफल रहा हूं। क्या यह सच है?

नहीं, आपने नहीं किया है। आप वास्तव में मूल्य को फिर से सौंप रहे हैं, और आप संदर्भ को पुन: संयोजित नहीं कर रहे हैं।

आपके उदाहरण में, जब आप int &ri = i; करते हैं, ri अपने जीवनकाल के लिए i पर बाध्य है। जब आप ri = j; करते हैं, तो आप बस j से ri का मान निर्दिष्ट कर रहे हैं। ri अभी भी i का संदर्भ बना हुआ है! और यह एक ही परिणाम में परिणाम के रूप में यदि आप के बजाय लिखा था i = j;

आप समझ संकेत अच्छी तरह से है, तो हमेशा T* const का एक अलंकारिक व्याख्या जहां T किसी भी प्रकार के रूप में संदर्भ के बारे में सोच रहे हैं।

0

ओपी ने संदर्भ के लिए असाइनमेंट के माध्यम से संदर्भित ऑब्जेक्ट को बदलने के लिए कहा और बहुत सही ढंग से बताया गया कि इसने संदर्भ वस्तु को संदर्भित किया है, संदर्भ नहीं। अब मैंने वास्तव में संदर्भ को बदलने और संभावित रूप से गंदे सामानों को खोजने के लिए एक और अधिक कठोर प्रयास किया है। पहले कोड। यह एक नव निर्मित ऑब्जेक्ट संदर्भ संदर्भ में पुन: असाइन करने का प्रयास करता है, फिर संदर्भ उर्फ ​​संदर्भित ऑब्जेक्ट को बदलता है, यह पता चलता है कि यह स्पष्ट रूप से संदर्भित वस्तुओं में दिखाई नहीं देता है और निष्कर्ष निकाला है कि हमारे पास C++ में एक खतरनाक सूचक का मामला हो सकता है। जल्दी से तैयार कोड के लिए खेद है।

using namespace std; 
vector<int>myints; 

auto &i = myints.emplace_back(); // allocate and reference new int in vector 
auto myintsaddr = &myints; auto myintfrontaddr = &myints.front(); // for future reference 
i = 1;        // assign a value to the new int through reference 
cout << hex << "address of i: 0x" << &i << " equals " << "address of 
myints.back(): 0x" << &myints.back() << '.' << endl; // check reference as expected 
i = myints.emplace_back();  // allocate new int in vector and assign to old reference variable 
i = 2;       // give another value to i 
cout << "i=" << i << ", myints={" << myints[0] << ", "<< myints[1] << '}' << endl; // any change to potentially referenced objects? 
cout << hex << "&i: 0x" << &i << " unequal to " << "&myints.back(): 0x" << &myints.back() << " as well as &myints.front(): 0x" << &myints.front() << endl; 
cout << "Myints " << (myintsaddr== &myints?"not ":"") << "relocated from " << myintsaddr << " to " << &myints << endl; 
cout << "Myints front() " << (myintfrontaddr == &myints.front() ? "not " : "") << "relocated from " << myintfrontaddr << " to " << &myints.front() << endl; 

आउटपुट:

address of i: 0x0063C1A0 equals address of myints.back(): 0x0063C1A0. 
i=2, myints={1, 0} 
&i: 0x0063C1A0 unequal to &myints.back(): 0x0063F00C as well as &myints.front(): 0x0063F008 
Myints not relocated from 0039FE48 to 0039FE48 
Myints front() relocated from 0063C1A0 to 0063F008 

निष्कर्ष: कम से कम मेरे मामले (VS2017) में संदर्भ स्मृति में ठीक उसी पते को रखा गया है, लेकिन संदर्भित मूल्यों (वेक्टर का हिस्सा) पुनः आवंटन किया गया है कहीं। संदर्भ मैं लटक रहा हो सकता है।