2013-07-29 5 views
5

सी ++ 11 इस में अब मान्य नहीं है:क्यों "गतिशील अपवाद" गारंटी ओवरहेड का कारण बनती है?

void foo() throw(); 

और बदला

void foo() noexcept; 

द्वारा this article में यह समझाया गया है कि इस का कारण (दूसरों के बीच, कि एक ही बात करने के लिए नीचे फोड़ा) यह है कि

सी ++ अपवाद विनिर्देशों को संकलित समय के बजाए रनटाइम पर चेक किया जाता है, इसलिए वे कोई प्रोग्रामर गारंटी नहीं देते हैं कि सभी अपवादों को संभाला गया है।

यह मेरे लिए कोई मतलब करता है, मुझे समझ नहीं आता क्यों throw() पहली जगह में गतिशील रूप से जांच की गई, या क्यों noexcept सामान्य स्टैक के बजाय std::terminate बुला (जो नहीं है के अलावा अन्य अपवाद गारंटी प्रदान नहीं करता है वास्तव में एक ठोस गारंटी आईएमओ)।

यह जांचना संभव नहीं होगा कि अपवादों को फेंक दिया गया है या नहीं संकलन समय के दौरान और यदि ऐसा होता है तो संकलन विफल हो जाएंगे? मैं इसे देखना, वहाँ मूलतः तीन मामलों रहे हैं:

void foo() noexcept 
{ 
    // 1. Trivial case 
    throw myexcept(); 

    // 2. Try-catch case 
    // Necessary to check whether myexcept is derived 
    // from exception 
    try 
    { 
     throw myexcept(); 
    } 
    catch(exception const & e) 
    {} 

    // 3. Nested function call 
    // Recursion necessary 
    bar(); 
} 
सी ++ हर प्रकार के instantiated जा रहा है में टेम्पलेट्स के साथ

, आवेदन संकलन हमेशा के लिए वैसे भी लेता है - तो क्यों noexcept परिवर्तन नहीं की जाँच करने के लिए कि क्या अपवाद दौरान फेंक दिया जाता है संकलक मजबूर करने के लिए समय संकलित करें?

मुझे लगता है कि एकमात्र कठिनाई यह है कि एक रन रनटाइम राज्यों के आधार पर फेंक सकता है या नहीं भी हो सकता है - लेकिन उस समारोह को मेरी राय में noexcept खुद को कॉल करने की अनुमति नहीं दी जानी चाहिए।

क्या मुझे कुछ याद आ रहा है, या संकलन समय को आगे बढ़ाने के लिए या कंपाइलर डेवलपर्स पर आसान नहीं होने का इरादा था?

+13

कंपाइलर को यह जानने का कोई तरीका नहीं है कि कहें, एक लाइब्रेरी फ़ंक्शन जिसे आप अपने फ़ंक्शन में कॉल करते हैं, अपवाद फेंकता है। – lapk

+4

'फेंक()' एक गारंटी है कि संकलक आपको बनाता है। 'noexcept' एक गारंटी है जो आप कंपाइलर को करते हैं। –

+0

@PetrBudnik: बेशक, कोई भी फ़ंक्शन 'अस्वीकरण' के रूप में चिह्नित नहीं किया जा सकता है। –

उत्तर

1

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

आपको यह भी ध्यान में रखना होगा कि गतिशील अपवाद विनिर्देश भी throw() की तुलना में काफी जटिल थे। यह एक प्रोग्रामर को मनमाने ढंग से सेट प्रकार निर्दिष्ट करने की अनुमति देता है जिसे फेंक दिया जा सकता है। इससे भी बदतर, यह निर्दिष्ट करना कि एक फ़ंक्शन foo फेंक सकता है इसका अर्थ है कि यह foo से प्राप्त कुछ भी फेंक सकता है।

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

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

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

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

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