2012-06-08 31 views
86

फेंक जबकि कुछ कोड मैं पर ठोकर खाई को देख:नई std :: अपवाद बनाम फेंक std :: अपवाद

throw /*-->*/new std::exception ("//... 

और मुझे हमेशा यही लगता है कि आप की जरूरत नहीं है/आप new यहाँ उपयोग नहीं करना चाहिए।
सही तरीका क्या है, ठीक है, अगर ऐसा कोई अंतर है?

बीटीडब्ल्यू जो मैं देख सकता हूं, "पावरशेल बूस्ट के साथ" grepping "libs कभी भी throw new का उपयोग नहीं करता है।

पीएस मुझे कुछ सीएलआई कोड भी मिला जो throw gcnew का उपयोग करता है। क्या वह ठीक है?

+0

मुझे लगता है कि 'फेंकना gcnew' उपयोगी होगा उदाहरण के लिए। यदि आप अपने अपवाद को पकड़ने के लिए प्रबंधित कोड चाहते हैं। क्या कोई मुझे उस पर सही कर सकता है? – jpalecek

+1

नेट पॉइंटर द्वारा अपवादों के साथ सौदा करता है, इसलिए जीसीएनयू फेंकना सही काम है। –

+1

@ सेबेस्टियन रेडल .Net "सूचक" संदिग्ध हो सकता है? हालांकि gcnew निश्चित रूप से नहीं है। 'सिस्टम :: अपवाद' आमतौर पर एकत्रित ढेर पर एक प्रबंधित वस्तु का संदर्भ होता है। मैंने हमेशा 'gcnew' के साथ फेंक दिया है और' सिस्टम :: अपवाद^'के साथ पकड़ा है। बेशक मैं सी ++/सीएलआई में हर समय 'अंततः' का उपयोग करता हूं, हालांकि अक्सर 'प्रयास' ब्लॉक में सी ++ अपवादों के साथ मिश्रण नहीं करता है, मुझे यकीन नहीं है कि क्यों। –

उत्तर

72

अपवादों को फेंकने और पकड़ने का पारंपरिक तरीका एक अपवाद वस्तु को फेंकना और संदर्भ (आमतौर पर const संदर्भ) को पकड़ना है। सी ++ भाषा में कंपाइलर को अपवाद ऑब्जेक्ट बनाने के लिए उचित कोड उत्पन्न करने और उचित समय पर इसे ठीक से साफ़ करने की आवश्यकता होती है।

एक गतिशील आवंटित वस्तु के लिए सूचक को फेंकना कभी अच्छा विचार नहीं है। अपवाद आपको त्रुटियों की स्थिति में अधिक मजबूत कोड लिखने में सक्षम होने के लिए माना जाता है। यदि आप परंपरागत तरीके से एक अपवाद वस्तु फेंकते हैं तो आप यह सुनिश्चित कर सकते हैं कि catch (...) द्वारा सही प्रकार नामकरण करने वाले कैच क्लॉज द्वारा पकड़ा गया है, चाहे उसे फिर से फेंक दिया जाए या नहीं, उचित समय पर इसे सही ढंग से नष्ट कर दिया जाएगा । (केवल एक ही अपवाद है कि यह कभी भी पकड़ा नहीं जाता है लेकिन यह एक गैर-पुनर्प्राप्ति योग्य स्थिति है जिसे आप इसे देखते हैं।)

यदि आप एक गतिशील आवंटित ऑब्जेक्ट में पॉइंटर फेंकते हैं तो आपको यह सुनिश्चित करना होगा कि जो भी हो कॉल स्टैक उस बिंदु की तरह दिखता है जिस पर आप अपना अपवाद फेंकना चाहते हैं वहां एक कैच ब्लॉक है जो सही सूचक प्रकार का नाम देता है और उचित delete कॉल करता है।आपका अपवाद कभी भी catch (...) तक पकड़ा नहीं जाना चाहिए जब तक कि उस ब्लॉक को अपवाद को फिर से फेंक दिया न जाए जो कि पकड़ा जाता है, एक और पकड़ ब्लॉक होता है जो अपवाद के साथ सही ढंग से सौदा करता है।

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

+1

"एक अपवाद ऑब्जेक्ट फेंक दें" स्टैक या मेरे दोस्त को ढेर किया है? ढेर या ढेर? (शायद मैं कहीं भी एक खराब वैश्विक उदाहरण देख रहा था) ओह और अगर ढेर, तो उचित दायरा क्या है? –

+0

@ebyrob: मुझे सच में यकीन नहीं है कि आप किस बारे में पूछ रहे हैं लेकिन ऐसा लगता है कि आप अपवाद ऑब्जेक्ट के भंडारण और/या जीवनकाल के बारे में जानना चाहते हैं जिसका उत्तर दिया जा सकता है [यहां] (http://stackoverflow.com/प्रश्न/1654150/गुंजाइश के- अपवाद-वस्तु-इन-सी)। यदि नहीं, तो आप एक अलग सवाल पूछने से बेहतर हो सकते हैं। –

26

अपवाद फेंकते समय new का उपयोग करने की आवश्यकता नहीं है।

बस लिखें:

throw yourexception(yourmessage); 

और के रूप में पकड़ने:

catch(yourexception const & e) 
{ 
     //your code (probably logging related code) 
} 

ध्यान दें कि yourexceptionstd::exception से प्रत्यक्ष या परोक्ष रूप प्राप्त करना चाहिए।

+5

क्यों? क्यों 'नया' का उपयोग नहीं करते? 'std :: अपवाद' से' yourexception' क्यों प्राप्त करें? – Walter

+0

जब मैं आलसी हूं (जो अक्सर अक्सर होता है) क्यों नहीं 'std :: अपवाद फेंकता है;' काम? g ++ इसे संकलित नहीं कर पाएगा ... –

+5

@ebyrob: 'std :: upgrade' एक प्रकार है, और आप * * * नहीं फेंक सकते हैं, आपको * ऑब्जेक्ट * फेंकना होगा। तो वाक्यविन्यास यह होना चाहिए: 'std :: अपवाद() फेंक दें; 'वह संकलित होगा। अब यह कितना अच्छा है, एक अलग सवाल है। – Nawaz

21

new std::exception फेंकना सही है यदि कॉल साइट std::exception* पकड़ने की अपेक्षा कर रही है। लेकिन कोई भी अपवाद के लिए सूचक को पकड़ने की उम्मीद नहीं करेगा। यहां तक ​​कि यदि आप दस्तावेज करते हैं कि आपका कार्य क्या करता है और लोग दस्तावेज़ पढ़ते हैं, तो वे अभी भी भूलने के लिए उत्तरदायी हैं और std::exception ऑब्जेक्ट के संदर्भ को पकड़ने का प्रयास करते हैं।

+25

'नया std :: अपवाद' फेंकना केवल तभी सही है जब कॉल साइट पॉइंटर पकड़ने की उम्मीद कर रही हो और आवंटन अपवाद के प्रबंधन को संभालने की उम्मीद कर रहा हो और ऐसा कोई भी मामला नहीं होगा जहां आप कार्य कर रहे हों कुछ ऐसा जो स्पष्ट रूप से सही सूचक ('पकड़ (...) 'या किसी भी हैंडलिंग को स्पष्ट रूप से पकड़ नहीं लेता है) अन्यथा कोई ऑब्जेक्ट रिसाव होगा। संक्षेप में, इसे "कभी नहीं" के रूप में अनुमानित किया जा सकता है। –

+0

यह उत्सुक है कि यह जवाब कैसे स्वीकार किया गया था, जब वास्तव में यह @ चार्ल्सबीली * टिप्पणी * है जो सही उत्तर है। –

+0

@ जॉन: यह मेरे दिमाग को भी पार कर गया। लेकिन मुझे लगता है कि एक-दो पंच का सूखा सारांश देने के साथ मेरा असर अच्छा प्रभाव पड़ता है और चार्ल्स आश्चर्यजनक रूप से उन तरीकों से विस्तार कर रहा है जो लोग इसके साथ सौदा करने के लिए भूल जाते हैं। बहुत बुरा आप अप-वोट टिप्पणियों से प्रतिष्ठा नहीं प्राप्त करते हैं, हालांकि। – Hurkyl

7

सी ++ पूछे जाने वाले प्रश्न इस पर एक अच्छी चर्चा की है:।

  1. https://isocpp.org/wiki/faq/exceptions#what-to-catch
  2. https://isocpp.org/wiki/faq/exceptions#catch-by-ptr-in-mfc

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

+2

सामान्य रूप से अक्सर पूछे जाने वाले प्रश्न बुरी तरह से बुलाए जाते हैं। आप मूल्य या संदर्भ से पकड़ सकते हैं। एक सूचक सिर्फ एक मान होता है (जिसे आप मूल्य या संदर्भ से पकड़ते हैं)। याद रखें कि 'ए' टाइप प्रकार 'ए *' से अलग है, इसलिए यदि मैं 'ए()' फेंकता हूं तो मैं 'कैच (ए * ई)' के साथ नहीं पकड़ सकता क्योंकि यह पूरी तरह से अलग प्रकार है। –

+0

ये लिंक अब टूटा हुआ है। – spanndemic

+1

मैंने लिंक @spanndemic – user1202136

संबंधित मुद्दे