2010-10-14 10 views
5

कॉन्स शुद्धता मुझे कुछ उलझन में है।सी ++ में कॉन्स का उपयोग करने का सही तरीका क्या है?

अंगूठे का क्या नियम आप तय करने के लिए जब कुछ स्थिरांक या नहीं होना चाहिए प्रयोग करते हैं?

उदा। इस उदाहरण

class MyClass 
{ 
    string ToString(); // this one? 
    const string& ToString(); // or this? 
    const string& ToString() const; // or this? 

    char* ToString(); // What about this? 
    const char* ToString(); // or this? 
    const char* ToString() const; // or this? 
    const char const* ToString(); // Is this legal? 
    const char const* ToString() const; // how about this? 
    char const* ToString(); // or even this? 
}; 

कॉन्स्ट पर विचार वास्तव में भ्रमित हो सकता है।

क्या इन सभी ToString विधियों के बीच अंतर हो सकता है?

अगर मैं सही ढंग से समझ, पहले एक एक नया स्ट्रिंग उद्देश्य यह है कि संशोधित किया जा सकता है, तो जरूरत पड़ने पर देता है। दूसरा एक रिटर्न एक निरंतर संदर्भ शायद यह स्ट्रिंग स्थिरांक & toString() होना चाहिए। तीसरा शायद एक बकवास है क्योंकि संदर्भ हमेशा स्थिर होते हैं क्या यह सही है?

सोचा मैं तुलना के लिए वहाँ में पुराने चार * संस्करणों फेंक था के रूप में मैं तरीकों कि वस्तु संकेत लौटने की क्या ज़रूरत है और मुझे यकीन है कि क्या वे स्थिरांक या नहीं होना चाहिए नहीं कर रहा हूँ।

मुझे लगता है कि मैं केवल स्थिरता की सीमाओं और लाभों को समझने की कोशिश कर रहा हूं और आगे कैसे निर्णय लेना चाहिए कि क्या कुछ होना चाहिए या नहीं और अलग-अलग स्थानों में स्थिरता रखने के बाद सही ढंग से लागू करना है।

संपादित करें: भी, मुझे लगता है कि '... छोड देता है क्वालिफायर' से निपटने के कैसे करते हैं। इसका वास्तव में क्या अर्थ है?

+0

दूसरे और तीसरे के बीच कोई अंतर नहीं है। – dan04

+9

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

+0

क्या आपने हर्ब सटर के गॉटव लेख को ["कॉन्स्ट सहीता"] पर पढ़ा है (http://www.gotw.ca/gotw/006.htm) यह एक उदाहरण वर्ग के माध्यम से जाता है और बताता है (1) 'कॉन्स्ट' क्या होना चाहिए और (2) 'const' का उपयोग करने के प्रभाव क्या हैं। यह निश्चित रूप से एक अच्छी शुरुआत जगह है। –

उत्तर

2

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

हैं, तो नहींconst के अंत में रखूँ हस्ताक्षर।

यदि फ़ंक्शन का उद्देश्य किसी संदर्भ या सूचक पैरामीटर को संशोधित करना है, पैरामीटर पर const डालें।

तो चर संदर्भित एक सूचक या संदर्भ द्वारा संशोधित किया जाना चाहिए, नहींconst प्रकार (याद रखें, const परिभाषा तुरंत पहले के भाग के लिए लागू होता है) पर डाल दिया है।

लौटे संदर्भ/सूचक को संदर्भित एक चर प्राप्त द्वारा बदला नहीं जाना चाहिए, तो प्रकार पर const रखूँ।

प्रश्न में दिए गए उदाहरण का उत्तर देना उद्देश्य कार्यों का जानने के बिना असंभव है। में delete के लिए ज़िम्मेदार कौन है, इस पर बहुत स्पष्ट दस्तावेज़ीकरण के साथ मेरी प्रवृत्ति string ToString() const और char* ToString() const का उपयोग करना होगा।


एक अतिरिक्त नोट के रूप में, const char* और char const* समान (unmodifiable वर्णों के लिए सूचक) कर रहे हैं। दूसरी ओर, char* const, संशोधित पात्रों के लिए एक अपरिवर्तनीय सूचक है।

+0

अपने WTF/मिनट योगदान है प्रकार के बाद [यहां] (http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2 "कोड की समीक्षा") :) – greatwolf

-1

मैं this पाया है एक उपयोगी गाइड

+2

-1 सी ++ एफक्यूए लाइट का लिंक। –

-1

अंगूठे का क्या नियम आप तय करने के लिए जब कुछ स्थिरांक या नहीं होना चाहिए का उपयोग करते हैं होने के लिए?

इसे हर जगह इस्तेमाल करें। फिर, इसका उपयोग तब करें जब आप ऑब्जेक्ट को संशोधित करने के लिए नोड करते हैं या किसी ऑब्जेक्ट को संशोधित कर सकते हैं जो ऑब्जेक्ट को संशोधित कर सकता है (यानी संदर्भ या प्रॉक्सी को आंतरिक स्थिति में लौटा सकता है)।

तीसरा शायद एक बकवास है क्योंकि संदर्भ हमेशा स्थिर होते हैं क्या यह सही है?

नहीं, यह सही नहीं है। एक संदर्भ एक उपनाम है, एक चर नहीं। इसलिए, आप एक पॉइंटर के साथ एक संदर्भ "बिंदु" को संदर्भित नहीं कर सकते हैं। हालांकि, आपके पास एक म्यूटेबल ऑब्जेक्ट (std::string&) का संदर्भ हो सकता है।

इन सभी ToString विधियों के बीच क्या अंतर होगा?

वे सभी काफी स्मृति प्रबंधन तकनीकों को लेकर मतभेद है, लेकिन एक उच्च स्तर पर है, वे सभी निम्नलिखित के अलावा एक ही बात करते हैं:

char* ToString(); 

कि ont एक परिवर्तनशील करने के लिए एक सूचक रिटर्न वर्णों की सरणी (संभावित रूप से आंतरिक स्थिति)।

ध्यान दें कि के परिवार:

char const* ToString(); 
const char* ToString(); // or this? 
const char const* ToString(); // Is this legal? 

एक ही बात लिखने के लिए सभी विभिन्न तरीके हैं। जब आप इसे लिखते हैं या नहीं, तो मूल्य के आधार पर मूल प्रकार सभी मूल होते हैं।

निम्नलिखित 2 पसंदीदा तरीका (अंत में एक अतिरिक्त const प्रदान की गई) C++ तार लौटने के होते हैं:

string ToString(); // this one? 
const string& ToString(); // or this? 

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

निम्न दो सही हैं, लेकिन मैं अभी भी आप std::string

const char* ToString() const; // or this? 
const char const* ToString() const; // how about this? 
+0

'कॉन्स्ट चार *' और 'char const * 'संशोधित पी हैं unmodifiable पात्रों के लिए ointers। 'char * const' संशोधित पात्रों के लिए एक अपरिवर्तनीय सूचक है। 'कॉन्स' जो भी पहले आता है उस पर लागू होता है या, यदि यह पहला है, तो इसके तुरंत बाद जो भी आता है। – Zooba

+0

ब्रांड्स के बाद 'const' अनावश्यक नहीं है: यह" * यह "ऑब्जेक्ट पर लागू होता है, न कि वापसी प्रकार। – aschepler

+0

ओह, उस पर थोड़ा तेज था। मैं इसे संपादित करूंगा। –

1

का उपयोग मैं हमेशा एक प्रारंभिक बिंदु के रूप सवालों के इन प्रकार के लिए इस FAQ का उपयोग किया है की सलाह देते हैं। http://www.parashift.com/c++-faq-lite/const-correctness.html

+0

यह कॉन्स्ट के बारे में मेरे सभी भ्रम को मंजूरी दे दी है। –

0

आप उन कार्यों को अधिभारित नहीं कर सकते हैं जिनके नाम और समान तर्क हैं लेकिन अलग-अलग रिटर्न प्रकार हैं। आप शायद यह जानते थे, लेकिन बस सुनिश्चित कर रहे हैं।

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

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

string वस्तुओं का उपयोग आमतौर पर सी-शैली char* संकेत का उपयोग कर के लिए बेहतर है, लेकिन जब से तुम से पूछते हैं: चौथे, char*, अन्य कोड परिवर्तन लौटे स्ट्रिंग, जो शायद एक बुरी बात है भीतर पात्रों दिया जाएगा। const char*, char const* और const char const* सभी एक ही बात हैं। char *const तकनीकी रूप से अलग है, लेकिन यह const int लौटने पर एक ही कारण के लिए रिटर्न प्रकार के रूप में बहुत कुछ नहीं करेगा: कॉलर बस प्रतिलिपि बना सकता है और फिर वापसी मूल्य बदल सकता है।

संक्षेप में, सबसे अच्छा रूपों होगा, क्रम में:

const string& ToString() const; 
string ToString() const; 
const char* ToString() const; 
0

सवाल में कुछ बदलाव बनाम char *string लौटने पर है। मुझे लगता है कि const चर्चा से संबंधित नहीं है (मुझे बताएं कि यह नहीं है); मैं string रिटर्न विविधताओं पर विचार कर रहा हूं।

class MyClass 
{ 
    string ToString();    // A 
    string & ToString();   // B (I added this) 
    const string& ToString();  // C 
    const string& ToString() const; // D 
}; 

मेरे वरीयताओं को इस क्रम में हैं:

  • वापसी प्रकार विनिर्देशक इस [: डी, ​​सी, बी, ए

    सभी रूपों में, const दो तरह से उपयोग किया जाता है डी में const डी]

    इसका मतलब है कि लौटाई गई वस्तु का उपयोग लौटाई गई वस्तु को संशोधित करने के लिए नहीं किया जा सकता है। वाक्य मजाकिया लगता है, है ना? खैर, किसी ऑब्जेक्ट को संशोधित करने के अन्य तरीके हो सकते हैं और यह const इसे रोक नहीं सकता है। यह FAQ item देखें।

  • वर्ग अपरिवर्तनीय [दूसरा const डी में]

    इसका मतलब है कि विधि उत्परिवर्तित नहीं करता है (संशोधित) वर्ग वस्तु।

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

शेष में, बी और सी दोनों ए से अधिक बेहतर हैं क्योंकि बी और सी एक संदर्भ देता है, जो ए में आवश्यक प्रति निर्माण निर्माण से बचाता है।

बी और सी के बीच, सी बेहतर है क्योंकि यह const संदर्भ लौटा रहा है।

+1

लेकिन वे अलग अलग अर्थ विज्ञान है। देखने की मेरी बात से, केवल जो कि समझ बनाने के (सबसे परिस्थितियों में) बी और डी तुम भी 'स्ट्रिंग toString() स्थिरांक की सोच सकते हैं,'। बी केवल तभी उपयोगी होता है जब आप उपयोगकर्ता को स्ट्रिंग को संशोधित करना चाहते हैं। डी को प्राथमिकता दी जाती है यदि आप 'MyClass' के स्ट्रिंग सदस्य के संदर्भ को वापस करने जा रहे हैं। यदि स्ट्रिंग सदस्य नहीं है (यानी फ़ंक्शन कॉल के दौरान गणना की जाती है), उपरोक्त फॉर्म का उपयोग करें। सी के लिए एक संभावित उपयोग है अगर MyClass स्ट्रिंग गणना करने के लिए है, लेकिन एक सदस्य चर के रूप में यह कैश (और इसलिए स्थिरांक नहीं है)। हालांकि, तो आप का उपयोग करना चाहिए 'mutable' – Gretchen

+0

हाँ, मैं भी विकल्प सी लगभग सभी परिस्थितियों में बच जाएंगे। अकेले डी समझ में आता है। _both_ बी को परिभाषित करना और अगर आप चाहते हैं संस्करण बी और संस्करण एक अकेला यदि स्ट्रिंग एक साधारण सदस्य होने के बजाय समारोह कॉल समय में गणना की जाती है मतलब होता है विकास समझ में आता है। – aschepler

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