क्या लूप के अंदर एक स्थानीय वस्तु का विनाशकर्ता को अगले पुनरावृत्ति से पहले बुलाया जाने की गारंटी है?


11

जब मेरे पास एक लूप होता है और इस लूप के अंदर एक नया स्टैक वैरिएबल बनता है (इसे ढेर और वेरिएबल पर ऑल्टर करते हुए इसे लूप बॉडी के अंदर घोषित नहीं किया जाता है), इस ऑब्जेक्ट का डिस्ट्रक्टर होता है जिसे गारंटीड किया जाता है जिसे अगले इरिगेशन शुरू होने से पहले बुलाया जाता है, या हो सकता है संकलक द्वारा अनियंत्रित लूप उस के बारे में कुछ बदलते हैं?


1
प्रति लूप अनियंत्रित होने से निष्पादन का क्रम नहीं बदलेगा। हालांकि, लूप समानांतरकरण ऐसा कर सकता है।
एड्रियन मोल

जवाबों:


8

से n4800:

§6.3.3 ब्लॉक स्कोप :

एक ब्लॉक में घोषित नाम (8.3) उस ब्लॉक के लिए स्थानीय है; इसमें ब्लॉक स्कोप है। इसकी संभावित गुंजाइश घोषणा के अपने बिंदु पर शुरू होती है (6.3.2) और इसके ब्लॉक के अंत में समाप्त होती है। ब्लॉक स्कोप पर घोषित एक वैरिएबल एक स्थानीय वैरिएबल है।

§10.3.6 Destructors :

एक विध्वंसक अंतर्निहित रूप से आह्वान किया जाता है [...] जब ब्लॉक जिसमें एक वस्तु बनाई जाती है बाहर निकलती है (8.7)

§4.1.1 सार मशीन :

इस प्रावधान को कभी-कभी "जैसा-अगर" नियम कहा जाता है, क्योंकि एक कार्यान्वयन इस दस्तावेज़ की किसी भी आवश्यकता की अवहेलना करने के लिए स्वतंत्र है, जब तक कि परिणाम ऐसा हो कि आवश्यकता का पालन किया गया था, जहां तक ​​कि अब तक के अवलोकन योग्य व्यवहार से निर्धारित किया जा सकता है कार्यक्रम

[जोर मेरा]

तो हाँ। लूप (जो एक ब्लॉक है) के अंत में आपका चर दायरे से बाहर हो जाता है और इसलिए इसके विध्वंसक को कहा जाता है जहां तक ​​कार्यक्रम के व्यवहार को देखने वाला कोई भी व्यक्ति बता सकता है


1
विध्वंसक कहा जाता है जब वहाँ के बारे में कुछ भी नहीं है।
स्टार्क

2
@ स्टार्क उन्हें ऐसा करने की अनुमति देता है, जैसा कि यह नियम है। मानक केवल अमूर्त मशीन के व्यवहार को निर्दिष्ट करता है। यकीन नहीं है कि अगर यह सब विस्तार में यहाँ जवाब में आवश्यक है।
मैक्स लैंगहॉफ

2
@ स्टार्क यह है, IMO, सवाल के लिए अप्रासंगिक। आप यह भी कह सकते हैं कि विध्वंसक इनलेट हो सकते हैं, और इसलिए callएड बिल्कुल नहीं। या, यदि वे प्रभावी रूप से (जैसे-यदि नियम) कुछ भी नहीं करते हैं, तो उत्पन्न ऐसे विध्वंसक के लिए कोई विधानसभा नहीं हो सकती है।
डैनियल लैंगर


2
@ स्टार्क कहां परिभाषित किया गया है ? ध्यान दें कि यह चर्चा प्रश्न के विषय से हटकर है। आप इस समस्या के बारे में एक और अलग सवाल पूछ सकते हैं।
डैनियल लैंगर

8

हाँ। जब आप "ब्लॉक" पर विचार करते हैं, जिसमें आप एक चर घोषित करते हैं, अर्थात किस जोड़ी के बीच ब्रेसिज़ की कल्पना करना आसान है। लूप अपने आप में एक ब्लॉक है, और जब यह समापन ब्रैकेट तक पहुंचता है, तो अगले पुनरावृत्ति से पहले, लूप में घोषित स्वचालित भंडारण चर के सभी विनाशकों को कहा जाता है।

संकलक द्वारा अनियंत्रित होने वाले लूप उस के बारे में कुछ बदल सकते हैं?

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


2
+1 अंगूठे के नियम के लिए, कोड लिखते समय कंपाइलर इंटर्नल के बारे में चिंता नहीं करनी चाहिए। मेरे जवाब में उसी भावना के साथ कुछ जोड़ने जा रहा था, लेकिन अब इसके पहले से ही
idclev 463035818

कॉपी-एलिसेंस और आरवीओ प्रोग्राम व्यवहार को बदलते हैं, है ना?
जीन-बैप्टिस्ट युनूस

@ जीन-बैपटिस्टयूनस वे संभावित रूप से कर सकते हैं, हालांकि, मानक उन्हें बहुत अधिक प्रति अनुमति देता है[class.copy.elision]
क्रिसम डे

सिर्फ ब्रेसिज़ की जोड़ी नहीं । आप लिख सकते हैं for(...) X x{};और xप्रत्येक निर्माण में ऑब्जेक्ट का निर्माण + विनाश किया जाएगा। लाइव डेमो । एक प्रासंगिक मानक अनुभाग stmt.iter / 2 है
डैनियल लैंगर

@DanielsaysreinstateMonica .59.5.2 के अनुसार [stmt.iter]यह पूरी तरह से समतुल्य है (जोर मेरा): "यदि एक पुनरावृत्ति-कथन में प्रतिस्थापन एक एकल कथन है और यौगिक-कथन नहीं है, तो यह ऐसा है जैसे यह एक यौगिक-कथन होने के लिए फिर से लिखा गया हो मूल कथन। " संक्षेप में, एक बयान के लिए ब्रेसिज़ के साथ या उसके बिना बिल्कुल एक ही चीज़ का मतलब है और ब्रेसिज़ निहित हैं। मैंने इसे स्पष्टता के लिए छोड़ दिया।
जेबीएल

2

विध्वंसक हर पुनरावृत्ति के लिए कहा जाता है। इस प्रकार कुछ मामलों में लूप के बजाय लूप के बाहर एक वैरिएबल घोषित करना तेजी से होता है। निम्नलिखित मामले को मानते हुए:

std::string temp;
for(int i = 0; i < 10; ++i){
    temp = arr[i];
    doSomething(temp);
}

लूप का उपयोग करने पर विध्वंसक को नहीं बुलाया जाता है। यह बस ओवरराइड करता है temp

लेकिन अगर आप std::string temp = arr[i]कंस्ट्रक्टर का उपयोग करते हैं और विनाशकर्ता को प्रत्येक पुनरावृत्ति के लिए कहा जाता है। मुझे लगता है कि अगर आपके पास एक लूप होता है जो कि बहुत बार निष्पादित होता है तो यह थोड़ा रनटाइम जोड़ता है।


ध्यान दें कि विध्वंसक कहा जा रहा है या नहीं केवल प्रदर्शन का सवाल नहीं है। जब आपके पास RAII प्रकार होता है, तो आप विशेष रूप से चाहते हैं कि विध्वंसक को हर पुनरावृत्ति पर बुलाया जाए
idclev 463035818

सच नहीं है। क्या 'अस्थायी' सामग्री का विध्वंसक पिछले पुनरावृत्ति से पकड़े हुए सही नहीं कहा जाता है जब अस्थायी नए मूल्य के साथ पुन: असाइन किया जाता है?
user1282931

मैं 100% निश्चित नहीं हूं। अगर आपको कुछ गलत लगा, तो मेरा उत्तर ठीक करें। :)
जूलियन श्नाबेल

0

विध्वंसक को अगले पुनरावृत्ति से पहले कहा जाता है


0

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.