2010-02-19 9 views
14

निम्न कोड एक, दो, तीन प्रिंट करता है। क्या यह सभी सी ++ कंपाइलर्स के लिए वांछित और सही है?स्कोप ब्लॉक समाप्त होने से पहले गैर-नामित सी ++ ऑब्जेक्ट्स क्यों नष्ट हो जाते हैं?


class Foo 
{ 
     const char* m_name; 
public: 
     Foo(const char* name) : m_name(name) {} 
     ~Foo() { printf("%s\n", m_name); } 
}; 

void main() 
{ 
     Foo foo("three"); 
     Foo("one"); // un-named object 
     printf("two\n"); 
} 
+0

डुप्लिकेट: http://stackoverflow.com/questions/1388685/local-variable-scope-question –

उत्तर

33

पूर्ण अभिव्यक्ति के अंत तक एक अस्थायी चर रहता है। यह अर्धविराम पर समाप्त होता है।

यह 12.2/3 में है:

अस्थायी वस्तुओं पूर्ण अभिव्यक्ति (1.9) कि (lexically) बिंदु है जहां वे शामिल होते हैं का मूल्यांकन करने में अंतिम चरण के रूप में नष्ट कर रहे हैं।

आपके व्यवहार की गारंटी है।

दो स्थितियां हैं, यदि मिले, तो अस्थायी जीवनकाल का विस्तार होगा। पहला यह है कि जब यह किसी ऑब्जेक्ट के लिए प्रारंभकर्ता होता है। दूसरा तब होता है जब एक संदर्भ अस्थायी से बंधे होते हैं।

+3

... 12.2/4 से शर्तों को जोड़ना, जो अस्थायी जीवनकाल को और भी आगे बढ़ा सकता है। – AnT

+0

@AndreyT: एर, हाँ। मुझे लगता है कि उल्लेख करना महत्वपूर्ण हो सकता है। – GManNickG

+1

मूल प्रश्न के संदर्भ में उल्लेख करना महत्वपूर्ण नहीं हो सकता है। लेकिन आपके स्पष्ट दावे को पढ़ने के बाद, "अभिव्यक्ति समाप्त होने पर एक अस्थायी चर का जीवनकाल समाप्त होता है" मैंने सोचा कि यह उल्लेख करने योग्य कुछ है। – AnT

6

इस तरह की एक अस्थायी वस्तु का दायरा केवल एक पंक्ति है। इसके बारे में सोचें, लाइन समाप्त होने के बाद आप इसे संदर्भित नहीं कर सकते हैं, तो ऑब्जेक्ट क्यों आसपास रहेगा?

यदि यह मामला नहीं था, तो कंपाइलर फ़ंक्शन कॉल में अस्थायी ऑब्जेक्ट्स को अनुकूलित करने में सक्षम नहीं होंगे।

3

हां, यह वांछित है।

Foo foo("three") एक सामान्य वस्तु बनाता है जो दायरा समाप्त होने पर नष्ट हो जाएगा।

Foo("one") एक अस्थायी वस्तु बनाता है, जो निर्देश के अंत में नष्ट हो जाता है [1]। क्यूं कर? क्योंकि निर्देश समाप्त होने के बाद आप इसका उपयोग नहीं कर सकते हैं।

[1] जानबूझकर सरलीकरण: मुझे अनुक्रम बिंदु कहा जाना चाहिए था।

+9

अनुक्रम बिंदु के साथ इसका कोई लेना-देना नहीं है। पूर्ण अभिव्यक्ति के अंत में अस्थायी सिरों का जीवनकाल, भले ही ऑब्जेक्ट बनाया गया "निर्देश" के अंत में अनुक्रम बिंदु हो। उदाहरण के लिए, 'फू ("ए") में, फू ("बी"), फू ("सी");' सभी तीन अस्थायी को बयान के अंत तक जीने की गारंटी है, भले ही मध्य में अनुक्रम बिंदु हों । – AnT

11

अस्थायी वस्तुओं के जीवनकाल को नियंत्रित करने वाले नियमों के पास स्कोप की धारणा से कोई लेना देना नहीं है। स्कोप नाम की संपत्ति है, और अस्थायी वस्तुओं के नाम नहीं हैं। दूसरे शब्दों में, अस्थायी वस्तुओं का कोई दायरा नहीं है।

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

const Foo &rfoo = Foo("one"); 

ऊपर अस्थायी के जीवनकाल से मिलान करने के रूप में लंबे समय के रूप में rfoo जीवन जीने होगा बढ़ाया जाएगा है।

+0

+1 'स्कोप किसी नाम की संपत्ति है, और अस्थायी वस्तुओं के नाम नहीं हैं।' क्या अस्थायी जीवन का समय 'कॉन्स्टिग क्वालिफायर' के संदर्भ में बाध्यकारी है? 'फू और आरएफयू = फू ("एक"); ' – Mahesh

+0

मैंने पढ़ा है कि अस्थायी जीवनकाल को केवल' कॉन्स्ट 'संदर्भ में बाध्यकारी किया जा सकता है। लेकिन उदाहरण http://ideone.com/nTVPZ वीएस 2010 पर ठीक काम करता है लेकिन जीसीसी पर नहीं (दोनों मामलों में 'यह' भी दिए गए लिंक में समान है, जो कि 'कॉन्स' क्वालीफायर के साथ भी अस्थायी जीवन को विस्तारित करता है वीएस पर)। क्या जीसीसी या वीएस सही है? – Mahesh

+0

@ माहेश: कोड मानक सी ++ में संकलित नहीं है, यही कारण है कि जीसीसी ने इसे अस्वीकार कर दिया। वीएस इसे केवल एक एक्सटेंशन के रूप में स्वीकार करता है क्योंकि आपके पास एक्सटेंशन सक्षम हैं। यदि आप वीएस में भाषा एक्सटेंशन अक्षम करते हैं, तो कोड वीएस में भी संकलित नहीं होगा। – AnT

0

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

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

+1

ढेर के बारे में स्पष्ट रूप से बात करना अनावश्यक है; उपयोग करने योग्य सी ++ कार्यान्वयन करना पूरी तरह से संभव है जो स्टैक का उपयोग नहीं करता है और इसके बजाय स्थैतिक स्थानों में सबकुछ आवंटित करता है। रजिस्टरों में छोटे अस्थायी मूल्यों को पारित करना भी संभव है, पता योग्य स्मृति में नहीं। –

+1

"एक कथन के दौरान किसी ऑब्जेक्ट का निर्माण और विनाश करना व्यर्थ है।" यदि आप दुष्प्रभावों के लिए या रूपांतरण श्रृंखला में नहीं करते हैं। यह इतना उपयोगी है कि एक प्रमुख सी ++ प्रोजेक्ट जैसे फ़ायरफ़ॉक्स में इस जगह पर हजारों रचनाएं हो सकती हैं। वे * बेहद * उपयोगी हैं। अगर यह ऑब्जेक्ट ब्लॉक के अंत तक रखा जाता है तो यह बदतर होगा, कैश का दबाव कई परियोजनाओं के प्रदर्शन को मार देगा, भले ही समग्र मेमोरी उपयोग महत्वपूर्ण रूप से परिवर्तित न हो। –

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