2010-04-30 9 views
40

नीचे दिए गए कोड को देखें। मुझे पता है कि यह स्थानीय चर के पते को वापस नहीं करता है, लेकिन यह अभी भी क्यों काम करता है और वैरिएबल i को मुख्य() से '6' में असाइन करता है? वैरिएबल को स्टैक मेमोरी से हटा दिया गया था तो यह केवल वैल्यू कैसे लौटाता है?स्थानीय या अस्थायी चर के संदर्भ में लौटने

#include <iostream> 

int& foo() 
{ 
    int i = 6; 
    std::cout << &i << std::endl; //Prints the address of i before return 
    return i; 
} 

int main() 
{ 
    int i = foo(); 
    std::cout << i << std::endl; //Prints the value 
    std::cout << &i << std::endl; //Prints the address of i after return 
} 
+19

आप बस भाग्यशाली हैं। ऐसा मत करो –

+3

आपको यह उपयोगी मिल सकता है: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – letsc

+0

मेरा मानना ​​है कि कुछ भाग्य इस तथ्य में है कि मैं foo() में unaltered (जो कंपेलरों को पाठ में स्थानांतरित करने या कहीं भी लंबे समय तक रहने की अनुमति देता है) – mho

उत्तर

22

आप भाग्यशाली हो गए। फ़ंक्शन से लौटने से आपके द्वारा अभी बाहर निकलने वाले स्टैक फ्रेम को तुरंत मिटाया नहीं जाता है।

बीटीडब्ल्यू, आपने कैसे पुष्टि की कि आपको 6 बार वापस मिला है? अभिव्यक्ति std::cout << &i ...i का पता मुद्रित करती है, इसकी कीमत नहीं।

+3

6 तब सामने आता है जब वह इसे मुख्य() में प्रिंट करता है। –

+2

@San: ठीक है, अब यह है कि @ डेव 18 ने सवाल संपादित किया। –

+1

क्षमा करें, मैंने इसके बाद प्रश्न पढ़ना होगा :) –

1

जबकि आपका फ़ंक्शन संदर्भ द्वारा एक पूर्णांक देता है, इसे तुरंत स्थानीय चर 'i' में मुख्य() में असाइन किया जाता है। इसका मतलब है कि foo() के लिए आवंटित स्टैक मेमोरी को रिटर्न असाइनमेंट के लिए काफी लंबा होना चाहिए। हालांकि यह खराब रूप है, यह आमतौर पर काम करता है। यदि आपने संदर्भ

int &i = foo(); 

यह विफल होने की अधिक संभावना होगी।

3

स्थानीय चर के लिए रिटर्निंग संदर्भ या सूचक अपरिभाषित व्यवहार है। अपरिभाषित व्यवहार का मतलब है, मानक संकलक को निर्णय छोड़ देता है। इसका मतलब है, अपरिभाषित व्यवहार कभी-कभी अच्छी तरह से काम करता है, और sometimes it doesn't

+4

और इसकी संभावनाएं अच्छी तरह से काम नहीं कर रही हैं, जो डेमो देखने वाले लोगों के महत्व पर निर्भर करती हैं। – KeithB

2

i का पता main() में कभी भी परिवर्तित नहीं होगा, लेकिन इसमें निहित मूल्य होगा। आप स्थानीय चर का संदर्भ ले रहे हैं और उस संदर्भ के बाद इसका उपयोग दायरे से बाहर हो गए हैं। (इंप्रेशन भाषा चेतावनी) मूल्य 6 स्टैक पर है। चूंकि आपने 6 डालने के बाद स्टैक के साथ कुछ भी नहीं किया है, इसके संदर्भ में अभी भी वही मान होगा। तो, जैसा कि अन्य ने कहा है, आप भाग्यशाली हो गए हैं।

देखने के लिए कितना भाग्यशाली, इस कोड को जो ढेर का उपयोग करता है के बाद आप foo() फोन चलाने की कोशिश:

#include <iostream> 
#include <ctime> 
#include <numeric> 

int& foo() 
{ 
    int i = 6; 
    std::cout << &i << " = " << i << std::endl; //Prints the address of i before return 
    return i; 
} 

long post_foo(int f) 
{ 
    srand((unsigned)time(0)); 

    long vals[10] = {0}; 
    size_t num_vals = sizeof(vals)/sizeof(vals[0]); 
    for(size_t i = 0; i < num_vals; ++i) 
    { 
     int r = (rand()%2)+1; 
     vals[i] = (i+f)*r; 
    } 

    long accum = std::accumulate(vals, &vals[num_vals], 0); 
    return accum * 2; 
} 

int main() 
{ 
    int &i = foo(); 
// std::cout << "post_foo() = " << post_foo(i) << std::endl; 
    std::cout << &i << " = " << i << std::endl; 
} 

जब मैं post_foo() कॉल पर टिप्पणी के साथ इस भाग गया, 6 ढेर और उत्पादन पर अभी भी था था:

002CF6C8 = 6 
002CF6C8 = 6 

... लेकिन जब मैं post_foo() करने के लिए कॉल अन-टिप्पणी की है और इसे फिर से भाग गया, 6 लंबे चला गया था:

001FFD38 = 6 
post_foo() = 310 
001FFD38 = 258923464 
संबंधित मुद्दे