2013-08-23 4 views
6

मैं वर्तमान में सी ++ पढ़ रहा हूं, और मैंने पढ़ा है कि संदर्भ द्वारा वापसी का उपयोग करते समय मुझे यह सुनिश्चित करना चाहिए कि मैं एक चर के संदर्भ को वापस नहीं कर रहा हूं जो फ़ंक्शन लौटने पर गुंजाइश से बाहर हो जाएगा।एक स्वचालित चर काम के संदर्भ को वापस क्यों करता है?

तो Add में क्यों कार्य करें cen संदर्भ द्वारा वापस किया गया है और कोड सही तरीके से काम करता है ?!

#include <iostream> 
using namespace std; 

class Cents 
{ 
private: 
int m_nCents; 

public: 
Cents(int nCents) { m_nCents = nCents; } 

int GetCents() { return m_nCents; } 
}; 

Cents& Add(Cents &c1, Cents &c2) 
{ 
    Cents cen(c1.GetCents() + c2.GetCents()); 
    return cen; 
} 

int main() 
{ 
    Cents cCents1(3); 
    Cents cCents2(9); 
    cout << "I have " << Add(cCents1, cCents2).GetCents() << " cents." << std::endl; 

    return 0; 
} 

मैं Win7 से अधिक codeblocks आईडीई उपयोग कर रहा हूँ:

यहाँ कोड है।

+6

क्योंकि यह अपरिभाषित व्यवहार है, यह ठीक काम करने के लिए प्रतीत होता है लेकिन फिर बाद में तोड़ सकता है, इस पर भरोसा नहीं किया जा सकता है। –

+3

क्या हो रहा है (फिर, यूबी के साथ, कुछ भी चला जाता है) यह है कि जब से आप 'एड' कहलाते हैं, तो आपने कुछ और नहीं कहा है, कुछ भी अभी तक स्मृति के टुकड़े को ओवरराइड नहीं किया गया है, जहां 'सीन' था, और इसलिए पुराना मूल्य अभी भी है। कहा जा रहा है, आप हमेशा उस पर भरोसा नहीं कर सकते हैं। –

+2

उन दोनों टिप्पणियों का शायद उत्तर –

उत्तर

7

यह undefined behavior है, यह ठीक से काम करता प्रतीत होता है लेकिन यह किसी भी समय तोड़ सकता है और आप इस कार्यक्रम के परिणामों पर भरोसा नहीं कर सकते हैं।

जब फ़ंक्शन निकलता है, तो स्वचालित चर को पकड़ने के लिए उपयोग की जाने वाली मेमोरी जारी की जाएगी और यह उस स्मृति को संदर्भित करने के लिए मान्य नहीं होगी।

मसौदा सी ++ मानक खंड में 3.7.3अनुच्छेद 1 का कहना है:

ब्लॉक गुंजाइश चर स्पष्ट रूप से घोषित रजिस्टर या नहीं स्पष्ट रूप से घोषित स्थिर या निर्वासन स्वत: भंडारण अवधि की है। इन इकाइयों के लिए भंडारण उस ब्लॉक तक रहता है जिसमें उन्हें निकास बनाया जाता है।

1

क्या हो रहा है (फिर से, यूबी के साथ, कुछ भी जाता है) यह है कि जब आप Add कहलाते हैं, तो आपने कुछ और नहीं कहा है, कुछ भी अभी तक स्मृति के टुकड़े को ओवरराइड नहीं किया गया है, जहां cen था, और इसलिए पुराना मूल्य क्या अभी भी वहां है। कहा जा रहा है, आप हमेशा उस पर भरोसा नहीं कर सकते हैं।

+0

और @GaryWalker ने अपनी टिप्पणी में कहा, कुछ भी कॉल करें जो 'Add' के बीच में स्टैक के टन का उपयोग करता है और इसे प्रिंट करता है; आप लगभग निश्चित रूप से कचरा मिल जाएगा। –

+0

वास्तव में आप खतरनाक संदर्भ का उपयोग करने के बाद कुछ भी भरोसा नहीं कर सकते हैं। – Ruslan

1

आपको ऑब्जेक्ट को ढेर में वापस करने के लिए एक memcpy करना चाहिए। हालांकि कोड काम करता है, दायरे से बाहर आने वाली वस्तुओं को वापस करते समय व्यवहार अपरिभाषित होता है। यह कोड हमेशा छोटा हो सकता है जब कोड छोटा होता है, क्योंकि जब फ़ंक्शन लौटाता है, तो फ़ंक्शन द्वारा कब्जे वाले स्टैक का हिस्सा साफ़ नहीं किया जाएगा और चूंकि फ़ंक्शन के भीतर स्थानीय चर वहां स्थान आवंटित किए जाएंगे, आमतौर पर आपके द्वारा प्राप्त मूल्य (आमतौर पर) आपके द्वारा अपेक्षित मानों को शामिल करते हैं। लेकिन जब आपके पास एक-दूसरे को कॉल करने वाले कई फ़ंक्शन होते हैं और प्रोग्राम बड़े होते हैं, तो आपका प्रोग्राम अपरिभाषित व्यवहार का उत्पादन शुरू कर देगा। संभवतः कभी-कभी गलती भी होती है।

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