2010-07-27 22 views
9

मैंने थोड़ा शीर्षक बदल दिया है क्योंकि मैंने सोचा कि यह अधिक उचित सवाल है।सी ++, क्या यह गोटो स्टेटमेंट जरूरी है?

क्या आप इसे पुन: सक्रिय करेंगे (गोटो के वैध उपयोग की तरह लगता है)? यदि, आप कथन पर जाने के लिए निम्न कोड को कैसे दोबारा प्रतिक्रिया देंगे?

if (data.device) { 
    try { 
     ... 
    } 
    catch(const std::exception&) { goto done; } 
    ... // more things which should not be caught 
done: ; 
} 

पूरा बयान

#ifdef HAVE_GPU 
      // attempt to use GPU device 
      if (data.device) { 
       try { 
        Integral::Gpu eri(S, R, Q, block.shell()); 
        eri(basis.centers(), quartets, data.device); 
       } 
       // if GPU fails, propagate to cpu 
       catch(std::exception) { goto done; } 
       data.device += size; 
       host_index.extend(block_index); 
       block_index.data.clear(); 
      done: ; 
      } 
#endif 

धन्यवाद

के बाद सबसे की वरीयता को देखा है, मैं ध्वज के साथ जाने का फैसला किया है, लेकिन श्री यॉर्क में टिप्पणी के साथ।

धन्यवाद हर कोई

+2

ब्लॉक में क्या देखे बिना मुश्किल कहना है, लेकिन एक और संभावना है कि कोड को किसी फ़ंक्शन में स्थानांतरित करना है। (शायद पठनीयता में भी सुधार हो सकता है, शायद नहीं।) तो अगर कुछ बुरा हुआ तो आप जल्दी ही वापस आ सकते हैं। – GManNickG

+4

कृपया कॉन्स्ट संदर्भ द्वारा पकड़ें, कृपया। –

+0

@GMan ने पूरा बयान जोड़ा। फंक्शन अधिक हो सकता है, क्योंकि कोई बंद नहीं है। – Anycorn

उत्तर

15
if (data.device) 
{ 
    bool status = true; 

    try 
    { 
     ... 
    } 
    catch(std::exception) 
    { 
     status = false; 
    } 

    if (status) 
    { 
    ... // more things which should not be caught 
    } 
} 
+0

कुछ हद तक स्पष्ट उत्तर नहीं दे सकता, लेकिन आप कौन सा पसंद करेंगे? स्थिति या गोटो? – Anycorn

+1

@aaa: मैं पूछने का सबसे अच्छा व्यक्ति नहीं हो सकता क्योंकि मैं एक अपरिपक्व एंटीगोटाइट हूं। :-) इससे पहले आज मुझे एक सवाल का जवाब देने के लिए डाउनवॉटेड किया गया था, "यहां यह है कि आप इसे बिना किसी काम के कैसे करेंगे: ..." लेकिन मेरे कारणों से कीवर्ड के लिए नापसंद की तुलना में स्केलेबिलिटी और ऑर्थोगोनैलिटी के साथ अधिक कुछ करना है। –

+5

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

2

आप बाहर अपवाद नहीं पकड़ सकते तो क्या होगा?

+0

अन्य तर्क इसे बहुत बदसूरत बना देगा, इसलिए मैं – Anycorn

3
if (data.device) { 
    bool ok = true; 
    try { 
     ... 
    } 
    catch(std::exception) { ok = false; } 

    if(ok) { 
     ... // more things which should not be caught 
    } 
} 
+0

पिछले उत्तरों में से एक में ऊपर दिखाए गए समान उत्तर। –

7

आप अपवाद को पकड़ने और एक विशिष्ट अपवाद है कि सशर्त ब्लॉक के बाहर से संभाला जा सकता rethrow कर सकते हैं।

// obviously you would want to name this appropriately... 
struct specific_exception : std::exception { }; 

try { 
    if (data.device) { 
     try { 
      // ... 
     } 
     catch(const std::exception&) { 
      throw specific_exception(); 
     } 

     // ... more things which should not be caught ... 
    } 
} 
catch (const specific_exception&) { 
    // handle exception 
} 
+1

धन्यवाद। मैंने इसके बारे में सोचा है, लेकिन यह मेरी राय में गोटो/ध्वज – Anycorn

+0

@aaa से अधिक जटिलता जोड़ता है: यह मेरी राय में, उन विकल्पों में से किसी एक से कहीं अधिक स्वच्छ है। इस मामले में एक 'गोटो' पूरी तरह से अनचाहे है, और यदि आप स्थिति ध्वज का उपयोग करते हैं तो आप कोड के एक ब्लॉक में दो अलग-अलग विफलता रिपोर्टिंग तंत्र (स्थिति झंडे और अपवाद) को मिलाकर समाप्त करते हैं, जो जटिलता को बहुत बढ़ाता है और इसे और अधिक कठिन बनाता है कोड के बारे में कारण। –

+0

* गोटो का अर्थ क्या है वॉरंट/अनचाहे *? 'गोटो 'का व्यवहार अच्छी तरह से परिभाषित किया गया है और (मुझे विश्वास है) जो आप उम्मीद करेंगे वह करेंगे, या नहीं? मैं मानता हूं कि एक बूल चेक जोड़ना * नहीं * वैसे भी जाने का तरीका है। –

1

कुछ ध्वज का उपयोग करने और सशर्त बयान जोड़ने के बारे में क्या?

int caught = 0; 
if (data.device) { 
    try { 
     /* ... */ 
    } catch (std::exception e) { caught = 1; } 
    if (!caught) { 
     // more stuff here 
    } 
    // done: ... 
} 
+5

क्या आपके पास 'बूल' प्रकार के खिलाफ कुछ है? –

8

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

कहा जा रहा है कि, मैं कहूंगा कि आपका कोड ठीक उसी तरह दिखता है जिसकी आखिर में आविष्कार किया गया था। बहुत दुखी सी ++ में ऐसा कुछ नहीं है ... तो शायद सबसे आसान समाधान इसे छोड़ना है।

+0

नरक हाँ! जाओ जाओ! जाओ जाओ जाओ! सेवा मेरे! – Gianni

+3

दुर्भाग्य से आखिरकार() सही समाधान नहीं है क्योंकि कोड का उपयोग केवल तभी किया जाता है जब कोई अपवाद नहीं होता है, अंत में दूसरी ओर इसका मतलब है कि इसे हमेशा निष्पादित किया जाना चाहिए (भले ही अपवाद मौजूद हों)। हालांकि अंततः सी # और जावा जैसी भाषाओं के लिए जरूरी है, लेकिन सी ++ के लिए इसकी आवश्यकता नहीं है क्योंकि एक ही चीज़ को लागू करने के लिए बेहतर तकनीकें हैं। हालांकि मैं आपके सभी अन्य बिंदुओं से सहमत हूं। जो टूटा नहीं है उसे ठीक न करें। –

+1

उचित उपयोग और 'प्रति से' की वर्तनी के लिए वोट दें। –

2

जब कुछ शर्त के आधार पर बाहर निकलने के लिए कोड की एक गुच्छा होती है, तो मेरा पसंदीदा निर्माण "डू {} जबकि (0)" लूप और "ब्रेक" का उपयोग करना उचित होता है। मुझे नहीं पता कि क्या ब्रेक; हालांकि, एक पकड़ में करेंगे। यदि "ब्रेक" काम नहीं करेगा तो "गोटो" आपकी सबसे अच्छी शर्त हो सकती है।

+0

यह हर तरह से 'गोटो' से भी बदतर है। – Thomas

+0

+1 यह 'गोटो' के समान ही खराब है, लेकिन अतिरिक्त चर जोड़ने और कोड में स्थितियों को जोड़ने से बेहतर है। और मुझे लगता है कि इनमें से कोई भी नया अपवाद प्रकार फेंकने से बेहतर है ... मैं अभी भी 'गोटो' पसंद करता हूं, लेकिन यह जवाब दूसरों के मुकाबले कम नहीं है :) –

1
catch(std::exception) { return; } 

यह चाल चलाना चाहिए। मैं निश्चित रूप से यह मान रहा हूं कि done वास्तव में एक फ़ंक्शन के अंत में है।

यदि अपवाद होने पर आपको अतिरिक्त कोड निष्पादित करने की आवश्यकता है, तो स्थिति लौटाएं या अपवाद को अधिक उचित स्तर पर अपवाद फेंक दें (जेम्स का जवाब देखें)।

मैं की तरह कुछ कल्पना कर रहा हूँ:

doStuff(...) { 
    bool gpuSuccess = doGPUStuff(...); 
    if (!gpuSuccess) { 
     doCPUStuff(...); 
    } 
} 
+0

और फ़ंक्शन में बाकी सबकुछ छोड़ देता है। – GManNickG

+0

जो करने के लिए सही काम हो सकता है, या कम से कम रिफैक्टर करने के लिए। –

+2

मुझे नहीं लगता कि 'किया गया:' वर्तमान में एक फ़ंक्शन का अंत है - इसके बाद कोड को GPU के बजाय CPU का उपयोग करने के लिए किया जाता है (जिसे या तो विफल या संकलित किया जाना चाहिए)। –

4

क्यों कोशिश ब्लॉक के अंदर अतिरिक्त कोड कदम नहीं ?:

#ifdef HAVE_GPU 
      // attempt to use GPU device 
      if (data.device) { 
       try { 
        Integral::Gpu eri(S, R, Q, block.shell()); 
        eri(basis.centers(), quartets, data.device); 
        data.device += size; 
        host_index.extend(block_index); 
        block_index.data.clear(); 
       } 
       // if GPU fails, propagate to cpu 
       catch(std::exception) { /* handle your exception */; } 
      } 
#endif 
+1

ओपी के कोड ने स्पष्ट किया कि पहले दो पंक्तियों में एक रेटेड ब्रेक पॉइंट होता है जिसे फेंकने की अनुमति है। आपका उदाहरण हर अपवाद को निगल देगा। 'Host_index।विस्तार() 'अब चुपचाप विफल होने की अनुमति है। –

+0

मूल रूप से आपकी कहानियां, जितनी संभव हो सके कोशिश ब्लॉक के अंदर कोड की न्यूनतम मात्रा डालें? –

+0

यदि उसने यह स्पष्ट किया, तो यह सवाल में नहीं था। पकड़ के भीतर टिप्पणी "अपने अपवाद को संभालें" पर ध्यान दें। यह कोड लिखने के लिए ओपी पर निर्भर है। –

4

मुझे लगता है कि इस का एक प्रकार आप के लिए काम कर सकते हैं।

// attempt to use GPU device 
if (data.device) 
{ 
    try 
    { 
     Integral::Gpu eri(S, R, Q, block.shell()); 
     eri(basis.centers(), quartets, data.device); 

     data.device += size; 
     host_index.extend(block_index); 
     block_index.data.clear(); 
    } 
    catch (const std::bad_alloc&) 
    { 
     // this failure was not because 
     // of the GPU, let it propagate 
     throw; 
    } 
    catch(...) 
    { 
     // handle any other exceptions by 
     // knowing it was the GPU and we 
     // can fall back onto the CPU. 
    } 
} 

// do CPU 

आप GPU पुस्तकालय को संपादित करने और सभी GPU अपवाद gpu_exception जैसे कुछ आधार दे सकता है, तो कोड बहुत सरल हो जाता है:

// attempt to use GPU device 
if (data.device) 
{ 
    try 
    { 
     Integral::Gpu eri(S, R, Q, block.shell()); 
     eri(basis.centers(), quartets, data.device); 

     data.device += size; 
     host_index.extend(block_index); 
     block_index.data.clear(); 
    } 
    catch (const gpu_exception&) 
    { 
     // handle GPU exceptions by 
     // doing nothing and falling 
     // back onto the CPU. 
    } 

    // all other exceptions, not being 
    // GPU caused, may propagate normally 
} 

// do CPU 

यदि इन काम के निचले, मुझे लगता है कि दूसरी सबसे बड़ी चीज है Steve's answer

4

ध्वज का थोड़ा अलग उपयोग। मुझे लगता है कि यह अमरदीप की तुलना में साफ है।

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

#ifdef HAVE_GPU 
    // attempt to use GPU device 
    if (data.device) { 
     bool dont_catch = false; 
     try { 
      ... 
      dont_catch = true; 
      ... // more things which should not be caught 
     } catch (...) { 
      if (dont_catch) throw; 
     } 
    } 
#endif 
+0

ओह, अच्छी सोच। :) – GManNickG

+1

@GMan: परिवर्तन किया गया - यह निश्चित रूप से प्रश्नकर्ता के कोड के लिए अलग व्यवहार है, लेकिन यह मूल्य बनाम संदर्भ पर एक तर्क बचाता है ;-) –

2

Am मैं कुछ याद आ रही है, या यह catch और try ब्लॉक के अंदर done: लेबल के बीच हिस्सा ले जाने के लिए बराबर नहीं हो सकता है?

#ifdef HAVE_GPU 
      // attempt to use GPU device 
      if (data.device) { 
       try { 
        Integral::Gpu eri(S, R, Q, block.shell()); 
        eri(basis.centers(), quartets, data.device); 
        data.device += size; 
        host_index.extend(block_index); 
        block_index.data.clear(); 
       } 
       // if GPU fails, propagate to cpu 
       catch(std::exception) {} 
      } 
#endif 
+1

+1: * यदि * ओपी ऐसा करना चाहता है, तो यह है सबसे सरल समाधान। –

+0

हां, आप कुछ याद कर रहे हैं। अब अगर कुछ भी बाहर फेंकने से पहले कोशिश करता था, तो इसका अपवाद सिर्फ खाया जाता है। – GManNickG

1

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

उदाहरण के लिए

:

void myFunc() 
{ 
    String mystr("heya"); 
    try 
    { 
     couldThrow(mystr); 
    } 
    catch(MyException& ex) 
    { 
     return; // String mystr is freed upon returning 
    } 

    // Only execute here if no exceptions above 
    doStuff(); 
} 

इस तरह, यह गलत जाना मुश्किल है

+0

सहमत हुए। बस इसे एक फ़ंक्शन में रखें, और जब आप चाहें तो वापस आएं, ठीक है, वापस आएं। – jalf

1

कारण गोटो आज पर सिकोड़ी है हम इन फैंसी बातें बुलाया "कार्यों" के बजाय है कि है। GPU कोड को अपने स्वयं के फ़ंक्शन में लपेटें, जो विफल होने पर जल्दी वापस आ सकता है।

फिर इसे अपने मूल कार्य से कॉल करें।

के बाद से वे शायद कुछ चर (data, host_index और block_index, यह तरह दिखता है) साझा करने के लिए की आवश्यकता होगी, उन्हें एक वर्ग में रखा, और इसके बारे में दो कार्यों के सदस्यों बनाते हैं।

void RunOnGpu(){ 
     // attempt to use GPU device 
     if (data.device) { 
      try { 
       Integral::Gpu eri(S, R, Q, block.shell()); 
       eri(basis.centers(), quartets, data.device); 
      } 
      // if GPU fails, propagate to cpu 
      catch(std::exception) { return; } 
      data.device += size; 
      host_index.extend(block_index); 
      block_index.data.clear();  
} 
void DoStuff() { 
#ifdef HAVE_GPU 
    RunOnGpu(); 
#endif 
} 
संबंधित मुद्दे