एक समारोह में समय से पहले वापसी की क्षमता


97

यह एक ऐसी स्थिति है जिसका मैं एक अनुभवहीन प्रोग्रामर के रूप में अक्सर सामना करता हूं और विशेष रूप से एक महत्वाकांक्षी, गति-गहन परियोजना के लिए सोच रहा हूं, जिसे मैं अनुकूलित करने की कोशिश कर रहा हूं। प्रमुख सी-लाइक लैंग्वेज (C, objC, C ++, Java, C #, आदि) और उनके सामान्य संकलक के लिए, क्या ये दोनों कार्य कुशलता से चलेंगे? संकलित कोड में कोई अंतर है?

void foo1(bool flag)
{
    if (flag)
    {
        //Do stuff
        return;
    }

    //Do different stuff
}

void foo2(bool flag)
{
    if (flag)
    {
        //Do stuff
    }
    else
    {
        //Do different stuff
    }
}

असल में, क्या कोई प्रत्यक्ष दक्षता बोनस / जुर्माना है जब breakआईएनजी या returnआईएनजी जल्दी? स्टैकफ्रेम कैसे शामिल है? क्या विशेष मामलों को अनुकूलित किया गया है? क्या कोई कारक हैं (जैसे कि इनलाइन करना या "डू स्टफ़" का आकार) जो इसे महत्वपूर्ण रूप से प्रभावित कर सकते हैं?

मैं हमेशा मामूली अनुकूलन पर बेहतर सुवाह्यता का प्रस्तावक हूं (मैं पैरामीटर सत्यापन के साथ बहुत कुछ देखता हूं), लेकिन यह इतनी बार आता है कि मैं एक बार और सभी के लिए एक तरफ चिंता करना चाहता हूं।

और मुझे समय से पहले अनुकूलन के नुकसान के बारे में पता है ... ऊ, वे कुछ दर्दनाक यादें हैं।

संपादित करें: मैंने एक उत्तर स्वीकार कर लिया है, लेकिन EJP के उत्तर में स्पष्ट रूप से बताया गया है कि क्यों का उपयोग returnव्यावहारिक रूप से नगण्य है (असेंबली में, returnफ़ंक्शन के अंत में एक 'शाखा' बनाता है, जो बहुत तेज़ है। शाखा पीसी रजिस्टर और एल्टर करती है। कैश और पाइपलाइन को भी प्रभावित कर सकता है, जो कि बहुत छोटा है।) विशेष रूप से इस मामले के लिए, इसका शाब्दिक कोई फर्क नहीं पड़ता क्योंकि दोनों if/elseऔर returnफ़ंक्शन के अंत तक एक ही शाखा बनाते हैं।


22
मुझे नहीं लगता कि इस तरह की चीजों का प्रदर्शन पर ध्यान देने योग्य प्रभाव पड़ेगा। बस एक छोटी सी परीक्षा लिखें और खुद देखें। Imo, पहला संस्करण बेहतर है क्योंकि आपको अनावश्यक घोंसले के शिकार नहीं मिलते हैं जो
रीडबेलिटी को

10
@SirVaulterScott, जब तक कि दो मामले किसी तरह से सममित नहीं होते हैं, जिस स्थिति में आप समरूपता को समान स्तर पर रखकर समरूपता को बाहर लाना चाहते हैं।
लूकी

3
SirVaulterScoff: गैर-जरूरी घोंसले के शिकार को कम करने के लिए +1
fjdumont

11
पठनीयता >>> सूक्ष्म अनुकूलन। जो भी इस तरह से बनाए रखा जाएगा के लिए और अधिक समझ में आता है जो भी करते हैं। एक मशीन कोड स्तर पर, ये दोनों संरचनाएं समान होती हैं जब एक काफी गूंगा कंपाइलर में खिलाया जाता है। एक अनुकूलन कंपाइलर दोनों के बीच गति लाभ के किसी भी समानता को मिटा देगा।
स्प्लिंटररेलिटी

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

जवाबों:


92

इसमें कोई अंतर नहीं है:

=====> cat test_return.cpp
extern void something();
extern void something2();

void test(bool b)
{
    if(b)
    {
        something();
    }
    else
        something2();
}
=====> cat test_return2.cpp
extern void something();
extern void something2();

void test(bool b)
{
    if(b)
    {
        something();
        return;
    }
    something2();
}
=====> rm -f test_return.s test_return2.s
=====> g++ -S test_return.cpp 
=====> g++ -S test_return2.cpp 
=====> diff test_return.s test_return2.s
=====> rm -f test_return.s test_return2.s
=====> clang++ -S test_return.cpp 
=====> clang++ -S test_return2.cpp 
=====> diff test_return.s test_return2.s
=====> 

दो कंपाइलरों में अनुकूलन के बिना भी उत्पन्न कोड में कोई अंतर नहीं है


59
या बेहतर: कम से कम एक निश्चित संकलक का एक संस्करण है जो दो संस्करणों के लिए समान कोड उत्पन्न करता है।
अंकलजीव

11
@UncleZeiv - यदि सभी संकलक स्रोत को निष्पादन प्रवाह ग्राफ मॉडल में अनुवाद नहीं करेंगे तो सबसे ज्यादा। यह एक कठिन कार्यान्वयन की कल्पना करना मुश्किल है जो उन दो उदाहरणों के लिए सार्थक रूप से विभिन्न प्रवाह रेखांकन देगा। एकमात्र अंतर जो आप देख सकते हैं, के बारे में है कि दो अलग-अलग कामों की अदला-बदली हो जाती है - और यहां तक ​​कि शाखा भविष्यवाणी को अनुकूलित करने के लिए या किसी अन्य मुद्दे के लिए जहां कई प्लेटफ़ॉर्म पसंद करते हैं, जहां प्लेटफ़ॉर्म पसंदीदा ऑर्डर निर्धारित करता है।
स्टीव


@UncleZeiv: क्लैंग पर भी परीक्षण किया गया और उसी परिणाम
दानी

मुझे समझ नहीं आ रहा है। यह स्पष्ट लगता है कि something()हमेशा निष्पादित किया जाएगा। मूल प्रश्न में, ओपी के पास Do stuffऔर Do diffferent stuffध्वज पर निर्भर करता है। मैं sur नहीं हूँ कि उत्पन्न कोड समान होगा।
ल्यूक एम

65

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

पठनीयता और स्थिरता पर ध्यान दें।

यदि आप यह देखना चाहते हैं कि क्या होता है, तो अनुकूलन के साथ इनका निर्माण करें और कोडांतरक आउटपुट को देखें।


8
@Philip: और हर किसी के साथ एक एहसान करो और इस बारे में चिंता करना बंद करो। आपके द्वारा लिखा गया कोड दूसरों द्वारा और साथ ही पढ़ा और बनाए रखा जाएगा (और यहां तक ​​कि आपको यह भी लिखना चाहिए कि दूसरों के द्वारा कभी नहीं पढ़ा जाएगा आप अभी भी आदतों को विकसित करते हैं जो आपके द्वारा लिखे गए अन्य कोड को प्रभावित करेगा जो दूसरों द्वारा पढ़ा जाएगा)। हमेशा जितना संभव हो उतना समझने के लिए कोड लिखें।
होवडाल

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

10
@johannes मुझे असहमत करते हैं। कंपाइलर आपके एल्गोरिथ्म को एक बेहतर के लिए नहीं बदलेगा, लेकिन यह अधिकतम पाइपलाइन दक्षता और अन्य लूप्स (विखंडन, संलयन, आदि) के लिए इतनी तुच्छ चीजों को प्राप्त करने के निर्देशों को पुन: व्यवस्थित करने के लिए एक अद्भुत काम नहीं करता है जो कि एक अनुभवी प्रोग्रामर भी तय नहीं कर सकता है। जब तक उसे सीपीयू आर्किटेक्चर का अंतरंग ज्ञान न हो, तो बेहतर प्राथमिकता क्या है।
फोरट्रान

3
@johannes - इस सवाल के लिए, आप यह मान सकते हैं कि यह करता है। इसके अलावा, सामान्य तौर पर, आप कभी-कभी कुछ विशेष मामलों में कंपाइलर से बेहतर अनुकूलन करने में सक्षम हो सकते हैं, लेकिन इन दिनों विशेषज्ञ ज्ञान का एक अच्छा हिस्सा लेता है - सामान्य मामला यह है कि ऑप्टिमाइज़र सबसे अधिक अनुकूलन लागू करता है जिसके बारे में आप सोच सकते हैं और ऐसा करते हैं व्यवस्थित रूप से, कुछ विशेष मामलों में ही नहीं। WRT इस सवाल का, संकलक शायद का निर्माण करेगी ठीक के लिए एक ही निष्पादन प्रवाह ग्राफ दोनों रूपों। एक बेहतर एल्गोरिदम चुनना एक मानवीय काम है, लेकिन कोड-स्तरीय अनुकूलन लगभग हमेशा समय की बर्बादी है।
स्टीव 314

4
मैं इससे सहमत हूं और असहमत हूं। ऐसे मामले हैं जब कंपाइलर को पता नहीं चल सकता है कि कोई चीज़ किसी और चीज़ के बराबर है। क्या आप जानते हैं कि यह अक्सर अनचाही शाखाओं की x = <some number>तुलना में तेजी से करने का तरीका है if(<would've changed>) x = <some number>जिससे वास्तव में चोट लग सकती है। दूसरी ओर, जब तक यह एक अत्यंत गहन ऑपरेशन के मुख्य पाश के अंदर नहीं होता, मैं इसके बारे में चिंता नहीं करता।
user606723

28

दिलचस्प जवाब: हालांकि मैं उन सभी (अब तक) से सहमत हूं, इस सवाल के संभावित अर्थ हैं जो अब पूरी तरह से अवहेलना कर रहे हैं।

यदि उपरोक्त सरल उदाहरण को संसाधन आवंटन के साथ विस्तारित किया गया है, और फिर संसाधनों की संभावित फ्रीजिंग के साथ त्रुटि की जांच हो रही है, तो तस्वीर बदल सकती है।

भोले दृष्टिकोण पर विचार करें शुरुआती लोग ले सकते हैं:

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 लौटना मुश्किल है। शायद मैं सिर्फ अकल्पनीय हूं ;-)

तो, हां, मुझे लगता है कि समय से पहले रिटर्न कोडिंग के सवाल में एक बड़ा अंतर है या नहीं। लेकिन मुझे यह भी लगता है कि यह केवल अधिक जटिल कोड में स्पष्ट है जो संकलक के लिए पुनर्गठन और अनुकूलन के लिए कठिन या असंभव है। संसाधन आवंटन खेल में आने के बाद आमतौर पर ऐसा होता है।


1
वाह, वाकई दिलचस्प। मैं निश्चित रूप से भोली दृष्टिकोण की असहनीयता की सराहना कर सकता हूं। हालांकि उस विशेष मामले पर अपवाद से निपटने में सुधार कैसे होगा? जैसे त्रुटि कोड पर catchब्रेक-कम switchस्टेटमेंट है?
फिलिप्पुस

@Philip ने मूल अपवाद हैंडलिंग उदाहरण को जोड़ा। ध्यान दें कि केवल गोटो में गिरावट की संभावना है। आपका प्रस्तावित स्विच (टाइपोफ़ (ई)) मदद करेगा, लेकिन तुच्छ नहीं है और डिजाइन पर विचार करने की आवश्यकता है । और याद रखें कि ब्रेक के बिना एक स्विच / केस डेज़ी-जंजीर लेबल के साथ गोटो की तरह है ;-)
cfi

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

1
ध्यान दें कि C ++ में आप इनमें से कोई भी तरीका नहीं अपनाएँगे, लेकिन यह सुनिश्चित करने के लिए RAII का उपयोग करेंगे कि संसाधनों को ठीक से साफ किया जाए।
मार्क बी

12

हालांकि यह ज्यादा जवाब नहीं है, लेकिन एक उत्पादन संकलक आपके द्वारा किए गए अनुकूलन से बहुत बेहतर होने वाला है। मैं इस प्रकार के अनुकूलन पर पठनीयता और स्थिरता का समर्थन करूंगा।


9

इस बारे में विशिष्ट होने के लिए, returnइच्छा को विधि के अंत में एक शाखा में संकलित किया जाएगा, जहां एक RETनिर्देश होगा या जो कुछ भी हो सकता है। यदि आप इसे छोड़ देते हैं, तो ब्लॉक के अंत elseको एक शाखा में elseब्लॉक के अंत तक संकलित किया जाएगा । तो आप इस विशिष्ट मामले में देख सकते हैं कि इससे कोई फर्क नहीं पड़ता।


पकड़ लिया। मुझे वास्तव में लगता है कि यह मेरे प्रश्न का उत्तर बहुत ही सलीके से देता है; मुझे लगता है कि यह सचमुच एक रजिस्टर जोड़ है, जो बहुत नगण्य है (जब तक कि शायद आप सिस्टम प्रोग्रामिंग कर रहे हैं, और तब भी ...) मैं इसे एक सम्मानजनक उल्लेख देने वाला हूं।
फिलिप गिनी

@Philip क्या रजिस्टर जोड़ रहा है? पथ में कोई अतिरिक्त निर्देश नहीं है।
लोरेन

खैर दोनों के पास पंजीकरण जोड़ होते। यह सब एक विधानसभा शाखा है, है ना? कार्यक्रम काउंटर के अलावा? मैं यहां गलत हो सकता हूं।
फिलिप गिनी

1
@Philip नहीं, एक विधानसभा शाखा एक विधानसभा शाखा है। यह निश्चित रूप से पीसी को प्रभावित करता है, लेकिन इसे पूरी तरह से पुनः लोड करने से हो सकता है, और इसके प्रोसेसर में साइड-इफ़ेक्ट भी होते हैं जैसे कि पाइपलाइन, कैश इत्यादि
लोर्ने

4

यदि आप वास्तव में जानना चाहते हैं कि क्या आपके विशेष संकलक और सिस्टम के लिए संकलित कोड में अंतर है, तो आपको खुद को संकलित करना होगा और विधानसभा को देखना होगा।

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

इसके बजाय, मनुष्यों को पढ़ने और बनाए रखने के लिए स्पष्ट तरीके से कोड लिखें, और संकलक को वह करने दें जो वह सबसे अच्छा करता है: अपने स्रोत से सर्वश्रेष्ठ विधानसभा उत्पन्न करें।


4

आपके उदाहरण में, वापसी ध्यान देने योग्य है। डिबगिंग करने वाले व्यक्ति के लिए क्या होता है जब रिटर्न एक पेज या दो से ऊपर / नीचे होता है जहां // अलग-अलग सामान होता है? अधिक कोड होने पर ढूंढना / देखना अधिक कठिन होता है।

void foo1(bool flag)
{
    if (flag)
    {
        //Do stuff
        return;
    }

    //Do different stuff
}

void foo2(bool flag)
{
    if (flag)
    {
        //Do stuff
    }
    else
    {
        //Do different stuff
    }
}

बेशक, एक फ़ंक्शन एक (या यहां तक ​​कि दो) पृष्ठों से अधिक नहीं होना चाहिए। लेकिन डिबगिंग पहलू को अभी तक किसी भी अन्य उत्तर में शामिल नहीं किया गया है। मुद्दा लेना!
cff

3

मैं नीले रंग के साथ दृढ़ता से सहमत हूं: पठनीयता और स्थिरता पहले!। लेकिन अगर आप वास्तव में चिंतित हैं (या बस सीखना चाहते हैं कि आपका कंपाइलर क्या कर रहा है, जो निश्चित रूप से लंबे समय में एक अच्छा विचार है), तो आपको अपने लिए देखना चाहिए।

इसका मतलब होगा एक डीकॉम्पिलेटर का उपयोग करना या निम्न स्तर के कंपाइलर आउटपुट (जैसे असेंबली लानुज) को देखना। C #, या किसी भी .Net भाषा में, उपकरण यहाँ प्रलेखित हैं आपको वह देगा जो आपको चाहिए।

लेकिन जैसा कि आप स्वयं देख चुके हैं, यह शायद समय से पहले का अनुकूलन है।


1

से फुर्तीली सॉफ्टवेयर शिल्प कौशल की एक पुस्तिका: स्वच्छ कोड

झंडे के तर्क बदसूरत हैं। एक समारोह में एक बूलियन पास करना वास्तव में भयानक अभ्यास है। यह तुरंत विधि के हस्ताक्षर को जटिल करता है, जोर से यह घोषणा करते हुए कि यह फ़ंक्शन एक से अधिक कार्य करता है। यह एक काम करता है अगर झंडा सच है और दूसरा अगर झंडा झूठा है!

foo(true);

कोड में पाठक को फंक्शन में जाने और फू (बूलियन फ्लैग) पढ़ने में समय बर्बाद करने के लिए बनाया जाएगा

बेहतर संरचित कोड आधार आपको कोड को अनुकूलित करने का बेहतर अवसर देगा।


मैं इसे केवल एक उदाहरण के रूप में उपयोग कर रहा हूं। क्या हो रहा है समारोह में एक इंट, डबल, एक वर्ग हो सकता है, आप इसे नाम देते हैं, यह वास्तव में समस्या के दिल में नहीं है।
फिलिप गिनी

आपके द्वारा पूछा गया प्रश्न आपके फ़ंक्शन के अंदर एक स्विच करने के बारे में है, अधिकांश मामले में, यह एक कोड गंध है। इसे कई तरीकों से हासिल किया जा सकता है और पाठक को उस पूरे कार्य को पढ़ने की ज़रूरत नहीं है, कहते हैं कि फू (28) का क्या अर्थ है?
युआन

0

विचार का एक स्कूल (उस समय इसे प्रस्तावित करने वाले एगहेड को याद नहीं कर सकता है) यह है कि सभी फ़ंक्शन को कोड को पढ़ने और डीबग करना आसान बनाने के लिए संरचनात्मक बिंदु से केवल एक रिटर्न बिंदु होना चाहिए। यह, मुझे लगता है, धार्मिक बहस की प्रोग्रामिंग के लिए अधिक है।

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


उह, मैंने सोचा कि इसे सफाई के साथ करना होगा (सी में कोडिंग करते समय)।
थॉमस ईडिंग

नहीं, कोई बात नहीं, जहां आप एक विधि छोड़ते हैं जब तक आप वापस लौटते हैं तब तक स्टैक वापस नीचे टकरा जाता है (यह सब "साफ किया गया" है)।
1

-4

मुझे खुशी है कि आप इस सवाल को उठा रहे हैं। आपको हमेशा शुरुआती रिटर्न पर शाखाओं का उपयोग करना चाहिए। वहां क्यों रुके? अपने सभी कार्यों को एक में मर्ज करें यदि आप कर सकते हैं (कम से कम जितना आप कर सकते हैं)। यह उल्लेखनीय है अगर कोई पुनरावृत्ति न हो। अंत में, आपके पास एक बड़े पैमाने पर मुख्य कार्य होगा, लेकिन इस तरह की चीज़ के लिए आपको जो चाहिए / चाहिए। बाद में, अपने पहचानकर्ताओं का नाम बदलें जितना संभव हो उतना छोटा हो। इस तरह जब आपके कोड को निष्पादित किया जाता है, तो नाम पढ़ने में कम समय खर्च होता है। आगे करते हैं ...


3
मैं बता सकता हूं कि आप मजाक कर रहे हैं, लेकिन डरावनी बात यह है कि कुछ लोग आपकी सलाह को गंभीरता से ले सकते हैं!
डैनियल प्राइडेन

डैनियल के साथ सहमत हूँ। जितना मुझे निंदक प्रिय है - इसका उपयोग तकनीकी दस्तावेज, श्वेतपत्र और प्रश्नोत्तर जैसे साइटों में नहीं किया जाना चाहिए।
सीएफआई

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