C ++ 03 थ्रो () के बीच अंतर C ++ 11 noexcept निर्दिष्ट करें


100

क्या रनटाइम और कंपाइल टाइम में क्रमशः जांचे जाने के अलावा throw()और कोई अंतर noexceptहै?

यह विकिपीडिया C ++ 11 लेख बताता है कि C ++ 03 थ्रो स्पेसर पदावनत हैं।
ऐसा क्यों है, noexceptजो संकलन के समय सभी को कवर करने में सक्षम है?

[नोट: मैंने इस प्रश्न और इस लेख की जाँच की , लेकिन वंचना के ठोस कारण को निर्धारित नहीं कर सका।]


7
इस अच्छे लेख के अनुसार,noexcept रनटाइम चेक को भी रोका जा सकता है। उनके बीच मुख्य अंतर यह है कि ब्रेकिंग noexceptकारणों std::terminateको तोड़ते समय throwकारण बनता है std::unexpected। इन मामलों में थोड़ा अलग स्टैक अनइंडिंग व्यवहार भी।
फिकटिक

कुछ अपवाद विनिर्देशों के साथ "संकलन समय" कुछ भी नहीं है जो दूसरों पर "रनटाइम" चेक किया गया है। यह सिर्फ C ++ अपवाद विनिर्देशों के विरोधियों द्वारा बनाया गया एक मिथक है।
जिज्ञासु

जवाबों:


129

अपवाद विशिष्टताओं को हटा दिया गया था क्योंकि अपवाद विनिर्देशक आमतौर पर एक भयानक विचार हैंnoexceptजोड़ा गया था क्योंकि यह एक अपवाद निर्दिष्ट का एक उपयोगी उपयोगी उपयोग है: यह जानते हुए कि जब कोई फ़ंक्शन अपवाद को नहीं फेंकेगा। इस प्रकार यह एक द्विआधारी विकल्प बन जाता है: ऐसे कार्य जो फेंक देंगे और जो कार्य नहीं करेंगे।

noexceptअधिक शक्तिशाली है throw()क्योंकि इसके अलावा अन्य सभी फेंक विनिर्देशक को हटाने के बजाय जोड़ा गया था noexceptnoexceptएक पैरामीटर हो सकता है जो संकलन-समय एक बूलियन में हल करता है। अगर बूलियन सच है, तो noexceptलाठी। यदि बूलियन गलत है, तो noexceptछड़ी नहीं होती है और फ़ंक्शन फेंक सकता है।

इस प्रकार, आप ऐसा कुछ कर सकते हैं:

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};

क्या CreateOtherClassफेंक अपवाद? यह हो सकता है, अगर Tडिफॉल्ट कंस्ट्रक्टर कर सकता है। हम कैसे बताएं? ऐशे ही:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};

इस प्रकार, CreateOtherClass() यदि दिए गए प्रकार के डिफ़ॉल्ट कंस्ट्रक्टर फेंकता है तो iff को फेंक देगा। यह अपवाद निर्दिष्टकर्ताओं के साथ प्रमुख समस्याओं में से एक को ठीक करता है: कॉल स्टैक को प्रचारित करने में उनकी अक्षमता।

आप ऐसा नहीं कर सकते throw()


+1 उपयोगी उत्तर, वैसे भी मेरे लिए। फिर भी एक जवाब खोज रहा है जो कहता है कि मैं क्यों उपयोग करना चाहता हूं noexcept। मैंने कभी throw()भी विनिर्देशक का उपयोग नहीं किया , कभी भी और यह निर्धारित करने का प्रयास कर रहा हूं कि क्या noexceptवास्तव में कोई लाभ प्रदान करता है (संकलक द्वारा जांचे गए दस्तावेज के अलावा)।
hmjd

बस इस stackoverflow.com/questions/10787766/… पाया ...
hmjd

1
@ नाइकोलोलस सहमत हैं। लेकिन अगर नोएसेप्ट की गारंटी होगी, तो कंपाइलर जांच कर सकता है कि डिस्ट्रक्टर में फंक्शन हो सकता है या नहीं। इस प्रकार एक प्रोग्रामर को चेतावनी देने में सक्षम होना कि कोई फ़ंक्शन नोसेप्ट है या नहीं।
एलेक्स

2
@NicolBolas रनटाइम कॉल करता है std::terminate। जो है भी बदतर ! कोड उन रिलीज़ में चुपके कर सकता है जिनके कार्य चिह्नित हैं noexcept और रनटाइम (ग्राहक साइटों पर अर्थ) उल्लंघन का पता चला है। मेरा मतलब था कि संकलक कोड उत्पन्न करने की गारंटी देता है जो अपवादों को पहली जगह पर नहीं फेंकता है।
एलेक्स

2
@ निचलोलस: एक और ध्यान देने योग्य अंतर। यदि किसी फ़ंक्शन को चिह्नित किया जाता है, throws()तो यदि एक अपवाद को फेंक दिया जाता है, तो स्टैक को उस फ़ंक्शन के दायरे तक अनजाने होना चाहिए (इसलिए फ़ंक्शन में सभी स्वचालित चर नष्ट हो जाते हैं) जिस बिंदु terminate()पर (के माध्यम से unexpected()) कहा जाता है । यदि किसी फ़ंक्शन को चिह्नित किया जाता है, noexceptतो यदि कोई अपवाद फेंका जाता है, तो समाप्ति कहा जाता है (स्टैक की अनइंडिंग कार्यान्वयन परिभाषित विस्तार है)।
मार्टिन यॉर्क

33

noexcept संकलन समय पर जाँच नहीं की जाती है।

एक कार्यान्वयन केवल एक अभिव्यक्ति को अस्वीकार नहीं करेगा, क्योंकि जब इसे निष्पादित किया जाता है, तो वह फेंकता है या एक अपवाद फेंक सकता है जिसमें युक्त फ़ंक्शन अनुमति नहीं देता है।

जब एक फ़ंक्शन घोषित किया जाता है noexceptया throw()अपवाद को फेंकने का प्रयास करता है तो एकमात्र अंतर यह है कि एक कॉल terminateऔर othe कॉल unexpectedऔर अपवाद हैंडलिंग की बाद की शैली को प्रभावी ढंग से हटा दिया गया है।


लेकिन अगर किसी वर्चुअल फंक्शन में throw()/ noexcept, कंपाइल टाइम चेकिंग है तो सुनिश्चित करें कि एक ओवरराइड भी है।
जिज्ञासु

2

std::unexpected() C ++ रनटाइम द्वारा कहा जाता है जब एक गतिशील अपवाद विनिर्देश का उल्लंघन किया जाता है: एक अपवाद एक फ़ंक्शन से फेंका जाता है जिसका अपवाद विनिर्देश इस प्रकार के अपवादों को मना करता है।

std::unexpected() सीधे कार्यक्रम से भी बुलाया जा सकता है।

किसी भी स्थिति में, std::unexpectedवर्तमान में स्थापित कॉल std::unexpected_handler। डिफ़ॉल्ट std::unexpected_handlerकॉल std::terminate

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