2008-11-16 16 views
14

कल, मुझे लगने इस तरह कोड लिखने:यदि आप C++ में कोई मान वापस नहीं करते हैं तो क्या होता है?

SomeStruct getSomeStruct() 
{ 
    SomeStruct input; 

    cin >> input.x; 
    cin >> input.y; 
} 
पाठ्यक्रम वास्तव में struct मैं अभी बनाया वापस जाने के लिए भूल का

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

उत्तर

7

क्या कोई और कुछ संरचना बनाई गई और कहीं भी शुरूआत हुई?

इस बारे में सोचें कि संरचना कैसे वापस आती है। यदि x और y दोनों 32 बिट हैं, तो 32-बिट आर्किटेक्चर पर एक रजिस्टर में फिट होना बहुत बड़ा है, और यह 64-बिट आर्किटेक्चर पर 64-बिट मानों पर लागू होता है (@ डेंटन जेनेट्री के उत्तर में उल्लेख किया गया है कि कितने सरल मान हैं लौटा), तो इसे कहीं आवंटित किया जाना है। इसके लिए ढेर का उपयोग करना अपर्याप्त होगा, इसलिए इसे ढेर पर आवंटित किया जाना है। लेकिन यह आपके getSomeStruct फ़ंक्शन के ढेर फ्रेम पर नहीं हो सकता है, क्योंकि यह फ़ंक्शन रिटर्न के बाद अब मान्य नहीं है।

इसके बजाय कंपाइलर कॉलर कहलाता है कि कॉलर कहलाता है (जिसे कॉलर के ढेर पर शायद कहीं भी कहा जाता है), बुलाए गए फ़ंक्शन को आवंटित स्थान पर एक छिपे हुए पॉइंटर को पास करके। तो, जिस स्थान पर इसे शून्य पर सेट किया जा रहा है वह कॉलर पर है, न कि आपके getSomeStruct फ़ंक्शन पर।

"नामित मूल्य रिटर्न ऑप्टिमाइज़ेशन" जैसी अनुकूलन भी हैं जहां अतिरिक्त प्रतियों को बढ़ाया जा सकता है।तो, क्या आपने लापता return का उपयोग किया था, परिणाम अस्थायी बनाने और इसकी प्रतिलिपि बनाने के बजाय, कॉलर द्वारा आवंटित स्थान पर सीधे बनाया जाएगा।

क्या हो रहा है इसके बारे में और जानने के लिए, आपको कॉलर फ़ंक्शन को देखना होगा। क्या यह एक "खाली" SomeStruct प्रारंभ करने (शून्य करने के लिए) है जिसके बाद आप बाद में अपने getSomeStruct फ़ंक्शन का रिटर्न मान असाइन करते हैं? या यह कुछ और कर रहा है?

2

मेरे लिए संकलक यह अनुमति नहीं दी: http://codepad.org/KkzVCesh

+0

ऐसा लगता है कि यह इसकी अनुमति नहीं देता है क्योंकि आपके पास आपके कंपाइलर को त्रुटियों के रूप में चेतावनी देने के लिए सेट अप किया गया है। क्या आपको लगता है कि यह मेरे मामले में चेतावनी स्तर सेट बहुत कम हो सकता है? –

20

एक समारोह है कि (स्पष्ट रूप से एक मूल्य के लौटने के बिना) एक मूल्य के वापस जाने के लिए घोषित किया जाता है के अंत से गिरने अपरिभाषित परिणाम की ओर जाता है। जीसीसी के लिए, आपको -Wall कमांड लाइन स्विच से शुरू करना चाहिए जो सबसे उपयोगी चेतावनियों को चालू करता है। विशिष्ट जीसीसी चेतावनी जो आपको इच्छित चेतावनी को नियंत्रित करती है -Wreturn-type है (जो -Wall में शामिल है, मैं बस पूर्णता के लिए इसका उल्लेख करता हूं)।

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

+1

मैं हमेशा आश्चर्यचकित हूं कि यह एक त्रुटि के बजाय केवल एक चेतावनी है। इससे मदद मिलती है इससे कहीं अधिक बार दर्द होता है। –

+0

सी में कुछ भी वापस नहीं करना कानूनी था। यह अभी भी अनिर्धारित था, लेकिन कम से कम यह कानूनी था। – Jonathan

+0

विशेष रूप से, अगर मैं एक 'std :: vector' या अन्य ऑब्जेक्ट को वापस करना भूल जाता हूं जो कुछ ढेर स्मृति का प्रबंधन करता है, तो ऑब्जेक्ट एक अमान्य स्थिति में छोड़ा जाएगा और इसलिए यह नहीं पता होगा कि समय आने पर खुद को कैसे नष्ट किया जाए। यह एक कठिन डीबगिंग सत्र के लिए बनाता है। – Bernard

8

अधिकांश आधुनिक सीपीयू आर्किटेक्चर के लिए कॉलिंग सम्मेलन कॉलर को फ़ंक्शन रिटर्न वैल्यू पास करने के लिए एक विशेष रजिस्टर निर्दिष्ट करते हैं। कॉलर फ़ंक्शन कॉल करता है, और फिर निर्दिष्ट रजिस्टर का उपयोग रिटर्न मान के रूप में करता है। यदि आप स्पष्ट रूप से कोई मूल्य नहीं लौटाते हैं, तो कॉलर तब भी उस रजिस्टर में जो भी कचरा होता है उसका उपयोग करेगा।

कंपाइलर फ़ंक्शन के भीतर आंतरिक गणना के लिए उपलब्ध सभी रजिस्टरों का भी उपयोग करेगा। रिटर्न वैल्यू रखने के लिए नामित रजिस्टर का उपयोग फ़ंक्शन के भीतर विविध गणना के लिए भी किया जाएगा। इस प्रकार जब आप रिटर्न वैल्यू निर्दिष्ट करना भूल जाते हैं तो यह सही नहीं है कि सही मूल्य को कॉलर पर चमत्कारिक रूप से वापस कर दिया गया है: आपके ऑब्जेक्ट को स्टोर करने के लिए पंजीकृत कंपाइलर।

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

1

आपको कोई चेतावनी नहीं मिली क्योंकि आपके पास -Wall -Werror चालू नहीं था। (जैसा कि अन्य उत्तरों में बताया गया है)

हालांकि मुझे लगता है कि आपको शायद परिणामस्वरूप शून्य-भरी संरचना मिल गई है क्योंकि कॉलर फ़ंक्शन में संभवतः स्पष्ट शून्य तर्कों के साथ स्टैक ऑब्जेक्ट का निर्माण किया गया था, या अन्यथा शून्य पर ढेर?

3

मुझे यह दिलचस्प लगता है।

  • माइक्रोसॉफ्ट कुलपति, सभी संस्करणों (VC6 के बाद से वैसे भी):

    error C4716: 'getSomeStruct' : must return a value

  • डिजिटल मंगल ग्रह डिफ़ॉल्ट विकल्प का इस्तेमाल किया के साथ, निम्नलिखित compilers निम्नलिखित व्यवहार जब GetSomeStruct() समारोह संकलन है :

    Warning 18: implied return of getSomeStruct at closing '}' does not return value

  • Comeau:

    warning: missing return statement at end of non-void function "getSomeStruct"

  • जीसीसी:

    कोई त्रुटि या चेतावनी

मानक (6.6 से वाक्य के निम्नलिखित जोड़े को देखते हुए। 3 अनुच्छेद 2):

एक अभिव्यक्ति के बिना एक वापसी कथन है कि केवल में कार्यों कि कोई मान नहीं है, , वापसी प्रकार शून्य के साथ एक समारोह, एक निर्माता (12.1), या एक नाशक (इस्तेमाल किया जा सकता 12.4)। ... से बहने वाला फ़ंक्शन का अंत के बराबर है, बिना किसी मूल्य के वापसी; वैल्यू-रिटर्निंग फ़ंक्शन में अपरिभाषित व्यवहार में परिणाम।

मैं कहूंगा कि एक संकलक के लिए इस मामले में कोई त्रुटि न देने का कोई कारण नहीं है। इतने सारे कंपाइलर क्यों केवल एक चेतावनी या कोई निदान नहीं देते हैं?

+0

मैं इस पुष्टि पर ऑब्जेक्ट करता हूं कि जीसीसी इस पर चेतावनी नहीं देता है। कृपया '-Wall' विकल्प के साथ जीसीसी चलाएं, और आपको यह मिलेगा:' चेतावनी: गैर-शून्य [-Wreturn-type] लौटने वाले फ़ंक्शन में कोई वापसी विवरण नहीं – Loomchild

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

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