गोटो रिसाव चर का उपयोग करेगा?


94

क्या यह सच है कि gotoविध्वंसक और चीजों को बुलाए बिना कोड के बिट्स में कूदता है?

जैसे

void f() {
   int x = 0;
   goto lol;
}

int main() {
   f();
lol:
   return 0;
}

xलीक नहीं होगी?


संबंधित: stackoverflow.com/questions/1258201/… (लेकिन मैं इसे खरोंच से, सफाई से करना चाहता था!)
हल्की दौड़

15
क्या "Won't x be leaked"मतलब है? प्रकार xएक अंतर्निहित डेटा प्रकार है। आप एक बेहतर उदाहरण क्यों नहीं चुनते हैं?
नवाज 14

2
@ नवाज़: उदाहरण बिल्कुल सही है। लगभग हर बार जब मैं किसी के बारे में बात करता हूं goto, तो वे सोचते हैं कि स्वचालित भंडारण अवधि चर भी किसी तरह "लीक" है। आप और मैं जानते हैं कि अन्यथा बिंदु के अलावा पूरी तरह से है।
ऑर्बिट

1
@ डेविड: मैं मानता हूं कि यह प्रश्न बहुत अधिक मायने रखता है जब चर में एक गैर-तुच्छ विध्वंसक होता है ... और मैंने टॉमालक के उत्तर में देखा और इस तरह का उदाहरण पाया। इसके अलावा, जबकि कोई intरिसाव नहीं कर सकता , इसे लीक किया जा सकता है । उदाहरण के लिए: void f(void) { new int(5); }लीक ए int
बेन वायगेट

प्रश्न को कुछ इस तरह क्यों न बदलें "दिए गए उदाहरण में, कोड निष्कासन पथ एफ () से मुख्य () स्टैक और अन्य रिटर्न-फंक्शन कार्यक्षमता को साफ किए बिना ट्रांसफर करेगा? क्या इससे कोई विनाशकारी होने की आवश्यकता होगी? कहा जाता है? C में समान है? " क्या दोनों प्रश्न की मंशा को बनाए रखेंगे, जबकि संभव गलतफहमी से बचेंगे?
जैक वी।

जवाबों:


210

चेतावनी: यह उत्तर केवल C ++ से संबंधित है ; सी में नियम काफी अलग हैं।


xलीक नहीं होगी?

नहीं, बिल्कुल नहीं।

यह एक मिथक है gotoजो कुछ निम्न-स्तरीय निर्माण है जो आपको C ++ के अंतर्निर्मित स्कोपिंग तंत्र को ओवरराइड करने की अनुमति देता है। (यदि कुछ भी हो, तो longjmpऐसा हो सकता है।)

निम्नलिखित यांत्रिकी पर विचार करें जो आपको लेबल (जिसमें caseलेबल शामिल हैं) के साथ "बुरा काम" करने से रोकते हैं ।


1. लेबल गुंजाइश

आप कार्यों में नहीं कूद सकते:

void f() {
   int x = 0;
   goto lol;
}

int main() {
   f();
lol:
   return 0;
}

// error: label 'lol' used but not defined

[n3290: 6.1/1]:[..] एक लेबल का कार्य वह कार्य है जिसमें यह प्रकट होता है। [..]


2. वस्तु आरंभीकरण

आप ऑब्जेक्ट आरंभीकरण पर नहीं जा सकते हैं:

int main() {
   goto lol;
   int x = 0;
lol:
   return 0;
}

// error: jump to label ‘lol’
// error:   from here
// error:   crosses initialization of ‘int x’

यदि आप ऑब्जेक्ट आरंभीकरण पर वापस कूदते हैं , तो ऑब्जेक्ट का पिछला "उदाहरण" नष्ट हो जाता है :

struct T {
   T() { cout << "*T"; }
  ~T() { cout << "~T"; }
};

int main() {
   int x = 0;

  lol:
   T t;
   if (x++ < 5)
     goto lol;
}

// Output: *T~T*T~T*T~T*T~T*T~T*T~T

[n3290: 6.6/2]:[..] एक लूप से बाहर, एक ब्लॉक से बाहर, या स्वचालित भंडारण अवधि के साथ एक प्रारंभिक चर के पीछे स्थानांतरण, इसमें स्वचालित भंडारण अवधि के साथ वस्तुओं का विनाश शामिल है, जो इस बिंदु पर गुंजाइश से दायरे में हैं, लेकिन इस बिंदु पर स्थानांतरित नहीं किया गया है । [..]

आप किसी वस्तु के दायरे में नहीं कूद सकते, भले ही यह स्पष्ट रूप से आरंभिक न हो:

int main() {
   goto lol;
   {
      std::string x;
lol:
      x = "";
   }
}

// error: jump to label ‘lol’
// error:   from here
// error:   crosses initialization of ‘std::string x’

... कुछ विशेष प्रकार की वस्तु को छोड़कर , जो भाषा को संभाल सकती है क्योंकि उन्हें "जटिल" निर्माण की आवश्यकता नहीं है:

int main() {
   goto lol;
   {
      int x;
lol:
      x = 0;
   }
}

// OK

[n3290: 6.7/3]:एक ब्लॉक में स्थानांतरित करना संभव है, लेकिन इस तरह से नहीं कि प्रारंभिककरण के साथ घोषणाओं को बायपास करें। एक प्रोग्राम जो उस बिंदु से कूदता है जहां एक स्वचालित भंडारण अवधि वाला चर उस बिंदु के दायरे में नहीं होता है जहां वह दायरे में होता है, तब तक बीमार होता है जब तक कि चर स्केलर प्रकार, वर्ग प्रकार के साथ एक तुच्छ डिफ़ॉल्ट निर्माता और एक तुच्छ विध्वंसक नहीं होता है, इन प्रकारों में से एक का cv-योग्य संस्करण, या पूर्ववर्ती प्रकारों में से एक का एक सरणी और बिना इनिशलाइज़र के घोषित किया गया है। [..]


3. अन्य वस्तुओं के दायरे में कूदना

इसी तरह, स्वचालित भंडारण अवधि वाले ऑब्जेक्ट "लीक" नहीं होते हैं जब आप उनके दायरे से बाहर होते हैंgoto :

struct T {
   T() { cout << "*T"; }
  ~T() { cout << "~T"; }
};

int main() {
   {
      T t;
      goto lol;
   }

lol:
   return 0;
}

// *T~T

[n3290: 6.6/2]:एक दायरे (हालांकि पूरा) से बाहर निकलने पर, स्वचालित भंडारण अवधि (3.7.3) के साथ ऑब्जेक्ट जो उस दायरे में बनाए गए हैं, उनके निर्माण के रिवर्स ऑर्डर में नष्ट हो जाते हैं। [..]


निष्कर्ष

उपरोक्त तंत्र यह सुनिश्चित करते हैं कि gotoआप भाषा को तोड़ने न दें।

बेशक, इसका मतलब यह नहीं है कि gotoकिसी भी समस्या के लिए आपको "उपयोग" करना चाहिए , लेकिन इसका मतलब यह नहीं है कि यह "बुराई" के रूप में नहीं है क्योंकि आम मिथक लोगों को विश्वास करने के लिए प्रेरित करता है।


8
आप ध्यान दें कि C इन सभी खतरनाक चीजों को होने से नहीं रोकता है।
डेनियल

13
@ डैनियल: सवाल और जवाब विशेष रूप से सी ++ के बारे में हैं, लेकिन निष्पक्ष बिंदु। हो सकता है कि हमारे पास मिथक को भांपते हुए एक और सवाल हो कि C और C ++ एक ही हैं;)
को ऑर्बिट में हल्की दौड़

3
@Tomalak: मुझे नहीं लगता कि हम यहां असहमत हैं। एसओ पर दिए गए जवाबों में से कई स्पष्ट रूप से कहीं दस्तावेज हैं। मैं सिर्फ यह बात कर रहा था कि यह जवाब देखने के लिए सी प्रोग्रामर को लुभा सकता है और यह मान लेता है कि अगर यह C ++ में काम करता है, तो इसे C में इसी तरह काम करना चाहिए
डैनियल

2
आप यह भी जोड़ना चाह सकते हैं कि इन सब के बारे में गहनता से बातें करना लेबल के लिए समान हैं।
प्लाज़्मा एचएच

12
वाह, मैंने अभी-अभी C ++ का शब्दार्थ गोटो के लिए तोड़ा था, लेकिन वे आश्चर्यजनक रूप से समझदार हैं! बहुत बढ़िया जवाब।
जोसफ गार्विन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.