दिलचस्प जवाब: हालांकि मैं उन सभी (अब तक) से सहमत हूं, इस सवाल के संभावित अर्थ हैं जो अब पूरी तरह से अवहेलना कर रहे हैं।
यदि उपरोक्त सरल उदाहरण को संसाधन आवंटन के साथ विस्तारित किया गया है, और फिर संसाधनों की संभावित फ्रीजिंग के साथ त्रुटि की जांच हो रही है, तो तस्वीर बदल सकती है।
भोले दृष्टिकोण पर विचार करें शुरुआती लोग ले सकते हैं:
int func(..some parameters...) {
res_a a = allocate_resource_a();
if (!a) {
return 1;
}
res_b b = allocate_resource_b();
if (!b) {
free_resource_a(a);
return 2;
}
res_c c = allocate_resource_c();
if (!c) {
free_resource_b(b);
free_resource_a(a);
return 3;
}
do_work();
free_resource_c(c);
free_resource_b(b);
free_resource_a(a);
return 0;
}
उपरोक्त समय से पहले लौटने की शैली के चरम संस्करण का प्रतिनिधित्व करेगा। ध्यान दें कि जब इसकी जटिलता बढ़ती है, तो समय के साथ कोड बहुत दोहराव और गैर-रखरखाव योग्य कैसे हो जाता है। आजकल लोग इन्हें पकड़ने के लिए अपवाद हैंडलिंग का उपयोग कर सकते हैं ।
int func(..some parameters...) {
res_a a;
res_b b;
res_c c;
try {
a = allocate_resource_a(); # throws ExceptionResA
b = allocate_resource_b(); # throws ExceptionResB
c = allocate_resource_c(); # throws ExceptionResC
do_work();
}
catch (ExceptionBase e) {
# Could use type of e here to distinguish and
# use different catch phrases here
# class ExceptionBase must be base class of ExceptionResA/B/C
if (c) free_resource_c(c);
if (b) free_resource_b(b);
if (a) free_resource_a(a);
throw e
}
return 0;
}
फिलिप ने सुझाव दिया, नीचे दिए गए गोटो उदाहरण को देखने के बाद, ऊपर के कैच ब्लॉक के अंदर ब्रेक-कम स्विच / केस का उपयोग करने के लिए । एक स्विच (टाइपोफ़ (ई)) हो सकता है और फिर free_resourcex()
कॉल के माध्यम से गिर सकता है लेकिन यह तुच्छ नहीं है और डिजाइन पर विचार करने की आवश्यकता है । और याद रखें कि ब्रेक के बिना एक स्विच / मामला बिल्कुल डेज़ी-जंजीर लेबल वाले गोटो जैसा है ...
जैसा कि मार्क बी ने बताया, C ++ में रिसोर्स एक्विजिशन को फॉलो करना अच्छा स्टाइल माना जाता है , संक्षेप में RAII है। अवधारणा का अभिप्राय है एक्वायर संसाधनों के लिए ऑब्जेक्ट इंस्टेंटेशन का उपयोग करना। संसाधनों को स्वचालित रूप से मुक्त किया जाता है जैसे ही ऑब्जेक्ट दायरे से बाहर हो जाते हैं और उनके विनाशकों को कहा जाता है। अन्योन्याश्रित संसाधनों के लिए, डीलक्लोकेशन के सही क्रम को सुनिश्चित करने के लिए और सभी प्रकार के ऑब्जेक्ट्स के लिए आवश्यक डेटा को उपलब्ध कराने के लिए विशेष ध्यान रखा जाना चाहिए।
या पूर्व अपवाद दिनों में कर सकते हैं:
int func(..some parameters...) {
res_a a = allocate_resource_a();
res_b b = allocate_resource_b();
res_c c = allocate_resource_c();
if (a && b && c) {
do_work();
}
if (c) free_resource_c(c);
if (b) free_resource_b(b);
if (a) free_resource_a(a);
return 0;
}
लेकिन इस सरलीकृत उदाहरण में कई कमियां हैं: इसका उपयोग केवल तभी किया जा सकता है जब आवंटित संसाधन एक-दूसरे पर निर्भर न हों (जैसे कि यह मेमोरी आवंटित करने के लिए इस्तेमाल नहीं किया जा सकता है, फिर एक फ़ाइलहैंड खोलना, फिर मेमोरी में हैंडल से डेटा पढ़ना। ), और यह रिटर्न वैल्यूज़ के रूप में इनक्रेडिबल, डिफरेंशियल एरर कोड प्रदान नहीं करता है।
कोड को तेज () रखने के लिए, कॉम्पैक्ट, और आसानी से पठनीय और एक्स्टेंसिबल लाइनस टॉर्वाल्ड्स ने कर्नेल कोड के लिए एक अलग शैली लागू की जो संसाधनों से संबंधित है, यहां तक कि कुख्यात गोटो का उपयोग इस तरह से किया जाता है जो बिल्कुल समझ में आता है :
int func(..some parameters...) {
res_a a;
res_b b;
res_c c;
a = allocate_resource_a() || goto error_a;
b = allocate_resource_b() || goto error_b;
c = allocate_resource_c() || goto error_c;
do_work();
error_c:
free_resource_c(c);
error_b:
free_resource_b(b);
error_a:
free_resource_a(a);
return 0;
}
कर्नेल मेलिंग सूचियों पर चर्चा का सार यह है कि गोटो स्टेटमेंट पर "पसंदीदा" होने वाली अधिकांश भाषा विशेषताएं अंतर्निहित गोटो हैं, जैसे कि विशाल, वृक्ष-जैसे अगर / और, अपवाद हैंडलर, लूप / ब्रेक / स्टेटमेंट जारी रखें, आदि। और उपर्युक्त उदाहरण में गोटो को ठीक माना जाता है, क्योंकि वे केवल एक छोटी दूरी पर कूद रहे हैं, स्पष्ट लेबल हैं, और त्रुटि स्थितियों का ट्रैक रखने के लिए अन्य अव्यवस्था के कोड को मुक्त करते हैं। इस सवाल पर भी यहां चर्चा की गई है ।
हालाँकि जो अंतिम उदाहरण में याद आ रहा है वह एक त्रुटि कोड को वापस करने का एक अच्छा तरीका है। मैं result_code++
प्रत्येक free_resource_x()
कॉल के बाद जोड़ने और उस कोड को वापस करने के बारे में सोच रहा था , लेकिन इससे उपरोक्त कोडिंग शैली के कुछ गति प्राप्त होते हैं। और सफलता के मामले में 0 लौटना मुश्किल है। शायद मैं सिर्फ अकल्पनीय हूं ;-)
तो, हां, मुझे लगता है कि समय से पहले रिटर्न कोडिंग के सवाल में एक बड़ा अंतर है या नहीं। लेकिन मुझे यह भी लगता है कि यह केवल अधिक जटिल कोड में स्पष्ट है जो संकलक के लिए पुनर्गठन और अनुकूलन के लिए कठिन या असंभव है। संसाधन आवंटन खेल में आने के बाद आमतौर पर ऐसा होता है।