2013-04-16 11 views
6

क्या मुझे const संशोधक पर ध्यान देना चाहिए जो कि आदिम प्रकारों के साथ काम कर रहा है? कौन सा वाक्य अधिक वाक्य रचनात्मक रूप से सही है और क्यों?सी ++ कॉन्स संशोधक आदिम प्रकार

प्रथम संस्करण:

float Foo::bar(float a, float b) 
{ 
    return (a + b)/2.0f; 
} 

दूसरा संस्करण:

const float Foo::bar(const float a, const float b) 
{ 
    return (a + b)/2.0f; 
} 

तीसरा संस्करण:

float Foo::bar(const float a, const float b) 
{ 
    return (a + b)/2.0f; 
} 

मैं जानता हूँ कि आदिम टाइप चर जब कुछ विधि के लिए गुजर कॉपी कर रहे हैं, लेकिन और तरीका क्या स्पष्ट है?

const float Foo::bar(const float& a, const float& b) const 
{ 
    return (a + b)/2.0f; 
} 

इस सह mpiler कि notthing बदल जाएगा सूचित, और यह भी मानकों के मान की प्रतिलिपि करने की कोई जरूरत:

उत्तर

13

मैं कहूंगा कि तीसरा संस्करण सबसे अधिक "सही" है।

आप संकलक को बताते हैं कि तर्क const हैं, जो सही है क्योंकि आप उन्हें संशोधित नहीं करते हैं। यह तर्कों को पारित करने के साथ-साथ गणनाओं के लिए अनुकूलन के साथ संकलक की सहायता कर सकता है।

और वापसी का प्रकार const नहीं है क्योंकि कॉलर लौटाए गए मान को संशोधित करना चाहता है। यदि कॉलर लौटाए गए मान को संशोधित नहीं करना चाहता है, तो यह कॉलर पर const चर को असाइन करने के लिए है।

मैं भी समारोह घोषणा करने के लिए const जोड़ा होता है, समारोह वस्तु में कुछ भी संशोधित नहीं करता है के बाद से:

float Foo::bar(const float a, const float b) const 
+1

+1 कॉन्स्ट सदस्य फ़ंक्शन (हालांकि ओपी ने जो पूछा उससे सहायक सहायक)। – wmorrison365

+2

"कॉलर लौटाए गए मान को संशोधित करना चाहता है" - हालांकि ऐसा करने के लिए उन्हें 'const_cast' (या सी-स्टाइल कास्ट) की आवश्यकता होगी, क्योंकि यह आदिम प्रकार की एक रैल्यू अभिव्यक्ति है। इसलिए यदि यह गैर-आधार है तो भी उन्हें बिना किसी कलाकार के गैर-कॉन्स्ट संदर्भ प्राप्त नहीं किया जा सकता है। निश्चित नहीं है कि हम वास्तव में * समर्थन करने की ज़रूरत है, लेकिन अधिक महत्वपूर्ण बात यह है कि यदि आपका फ़ंक्शन क्लास प्रकार की 'const' ऑब्जेक्ट देता है जो आमतौर पर खराब होता है, क्योंकि यह इससे आगे बढ़ता है या इसके गैर-कॉन्स्ट सदस्य फ़ंक्शन को कॉल करता है। –

+0

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

0

सबसे अच्छा तरीका यह AFAIK है।

+4

यह दूसरों की तुलना में बेहतर क्यों है ?? यदि आप मूल्य से गुजरते हैं तो आप मूल डेटा को भी संशोधित नहीं करते हैं।यदि आप संदर्भ पास करते हैं - मूल्य की कोई प्रति नहीं, लेकिन संदर्भ की प्रति है – nogard

+0

यह संकेत के कारण अतिरिक्त ओवरहेड भी उत्पन्न कर सकता है (यदि इसे ऑप्टिमाइज़ नहीं किया गया है) संदर्भ के रूप में मूल रूप से दृश्यों के पीछे एक सूचक है। –

1

वहाँ सब पर 2 और 3 संस्करणों के बीच कोई अंतर नहीं है। टाइप करें जो टाइप करने के लिए सबसे छोटा है :)

पहले और तीसरे के बीच थोड़ा अंतर है। यदि आप गलती से a और b फ़ंक्शन के अंदर संशोधित करने से डरते हैं तो आप तीसरे को पसंद कर सकते हैं।

+0

हालांकि दूसरे और तीसरे उत्तरों के बीच एक अंतर है। दूसरा एक 'कॉन्स फ्लोट' देता है जिसका अर्थ यह है कि वह जिस मूल्य को लौटाता है उसे बदला नहीं जा सकता है। तीसरे में आप निश्चित रूप से कर सकते हैं। – JasoonS

0

संक्षिप्त उत्तर: इससे कोई फर्क नहीं पड़ता।

लंबा उत्तर: चूंकि आप मूल्य से दो तर्क पारित कर रहे हैं और तर्क द्वारा तर्क वापस कर रहे हैं। इनमें से कोई भी ठीक है, लेकिन आप आमतौर पर पहले संस्करण को देखेंगे।

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

1

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

इसके अतिरिक्त, मूल्य पारित होने से संबंधित किसी भी संभावित सहमति/अस्थिरता के मुद्दों को पारित किया जा रहा है।

यह "यहां अनुकूलित करने का प्रयास न करें" का मामला है।

कॉन्स्ट द्वारा लौटने की शैली शैली है। मैं आम तौर पर नहीं करता, दूसरों को सिर्फ अगर किसी ने वापसी मूल्य के साथ कुछ करने के लिए गोनिग किया है तो पसंद करते हैं। इसके बाद आप लोगों को आर-वैल्यू संदर्भ द्वारा उन्हें वापस कर पाएंगे ...

मैं आमतौर पर आपके पहले विकल्प के लिए जाऊंगा। दूसरा विकल्प मूल्य से गुजरता है (कॉन्स का उपयोग करने के लिए आवश्यक नहीं) और कॉन्स वैल्यू द्वारा लौटाया जाता है।

+0

"अगला आप लोगों को आर-वैल्यू संदर्भ द्वारा वापस लौट पाएंगे" - जो यूबी को उकसाएगा, क्योंकि आप किसी स्थानीय ऑब्जेक्ट के सादे संदर्भ को वापस करने से कहीं अधिक स्थानीय ऑब्जेक्ट के लिए एक रावल्यू संदर्भ वापस नहीं कर सकते हैं। उम्मीद है कि उन लोगों को काफी जल्दी ठीक किया जा सकता है। –

2

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

const पैरामीटर पर क्वालीफायर केवल एक उद्देश्य है: फ़ंक्शन बॉडी को const योग्य तर्कों को संशोधित करने से रोकें।

अपने उदाहरण कोड के विशिष्ट मामले में, विधि Foo::bar तर्कों को संशोधित नहीं करता है, इसलिए const क्वालीफायर का उपयोग करने से कोई प्रभाव नहीं पड़ता है।

हालांकि, आप सभी मामलों में डिफ़ॉल्ट रूप से const का उपयोग करना चाह सकते हैं, और केवल उन्हीं स्थितियों के लिए इसे हटाएं जहां आप संशोधन की अनुमति देना चाहते हैं। इसलिए, इसे Foo::bar के मानकों पर लागू करना एक अच्छा विचार है। मुझे लगता है कि यह अच्छा अभ्यास है, हालांकि मैं स्वीकार करूंगा कि मैं शायद ही कभी इसका इस्तेमाल करता हूं, क्योंकि शोर के कारण यह घटता है, जो पठनीयता को कम कर सकता है।

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

सब कुछ, const क्वालीफायर जितना संभव हो उतना उपयोग करने से कोड कम त्रुटि प्रवण बनाने में मदद मिलेगी, और परिणामी प्रोग्राम को अनुकूलित करने में संकलक को भी मदद कर सकता है।

इन प्रकार के लिए एक संदर्भ का उपयोग करते हुए हालांकि कोई महत्वपूर्ण परिवर्तन नहीं करना चाहिए, अगर इन प्रकार के एक सीपीयू रजिस्टर में मानों फिटिंग का वर्णन (जो आम तौर मामला है),

तो, विधि के सभी तीन संस्करणों चाहिए उसी जेनरेट असेंबली कोड पर उबाल लें।

आदिम वापसी प्रकार के विशेष मामले में, इससे कोई फर्क नहीं पड़ता। वापसी मूल्य को const योग्यता में आगे और पीछे परिवर्तित किया जा सकता है।

अन्य ने फ़ंक्शन पर const क्वालीफायर के हित का भी उल्लेख किया है। मूल प्रश्न दायरे से बाहर, मैं यह भी कहूंगा कि जब संभव हो तो यह वास्तव में बेहतर होता है (Foo::bar के लिए) const के रूप में फ़ंक्शन को अर्हता प्राप्त करने के लिए।

+1

"कंपाइलर अनुकूलन में भी मदद करेगा" - * होगा * थोड़ा मजबूत है। मैंने एक सवाल पूछा http://stackoverflow.com/questions/1121791, बहुत समय पहले, और इसका जवाब यह साबित हुआ कि एक आदिम चर को कॉन्स्ट-क्वालिफाइंग करने के लिए जीसीसी 3 को अनुकूलित करने में मदद मिली, लेकिन जीसीसी 4 पर्याप्त स्मार्ट नहीं था मदद। –

+0

अच्छी तरह से, शायद। प्राचीन प्रकार के लिए शायद यह वास्तव में बहुत मायने रखता नहीं है। – didierc

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