दिलचस्प पोस्ट
एक्लिप्से से एनटीएलएम को निकालना बहुत खराब बढ़ावा: lexical_cast प्रदर्शन कोयोनर 2 @ व्यूबिल * एनजीआईफ़ में Google Chrome एक्सटेंशन के लिए ब्रॉसर बंद करें पर ईवेंट? PHP सभी संयोजनों को ले अनगिनत सीग्यू के साथ डेटा पास करना Hadoop "अपने मंच के लिए मूल-हदीस पुस्तकालय लोड करने में असमर्थ" चेतावनी "अवैध निर्देश: 4" त्रुटि क्या है और "-मॅकोक्स-वर्जन-मिन = 10.x" क्यों ठीक है? कैसे div की प्रतिशतता चौड़ाई को माता-पिता की तुलना में बनाइए और व्यूपोर्ट नहीं C ++ टेम्पलेट कंस्ट्रक्टर `पाप` के अपरिभाषित संदर्भ क्या गिटौब को आईडी याद है? कस्टम तस्वीर के साथ फेसबुक एपीआई पोस्ट लिंक 'प्रिंट' स्टेटमेंट जोड़कर डीबगिंग करने का उचित नाम क्या है हमें जावा में इंटरफेस की आवश्यकता क्यों है?

क्या मुझे कंस ऑब्जेक्ट्स वापस आना चाहिए?

Effective C++ मद 03 में, जब भी हो सके कॉन्स्ट का उपयोग करें।

 class Bigint { int _data[MAXLEN]; //... public: int& operator[](const int index) { return _data[index]; } const int operator[](const int index) const { return _data[index]; } //... }; 

const int operator[] int& operator[] से अंतर करता है

लेकिन क्या बारे में:

 int foo() { } 

तथा

 const int foo() { } 

ऐसा लगता है कि वे समान हैं

मेरा प्रश्न यह है, क्यों कि हम const int operator[](const int index) const बजाय int operator[](const int index) const ?

Solutions Collecting From Web of "क्या मुझे कंस ऑब्जेक्ट्स वापस आना चाहिए?"

गैर-स्तर प्रकार के रिटर्न प्रकारों पर शीर्ष स्तर के सीवी-क्वालिफायर को नजरअंदाज किया जाता है। इसका अर्थ है कि अगर आप लिखते हैं:

 int const foo(); 

वापसी प्रकार int यदि वापसी का प्रकार एक संदर्भ है, निश्चित रूप से, const अब शीर्ष स्तर नहीं है, और इसके बीच का अंतर:

 int& operator[]( int index ); 

तथा

 int const& operator[]( int index ) const; 

महत्वपूर्ण है (ध्यान दें कि कार्य घोषणाओं में, ऊपर की तरह, किसी भी शीर्ष स्तर सीवी-क्वालिफायर को भी नजरअंदाज किया जाता है।)

भेद भी क्लास प्रकार के रिटर्न वैल्यू के लिए प्रासंगिक है: यदि आप T const वापस करते हैं, तो कॉलर लौटा मूल्य पर गैर-कॉन्स्ट कार्यों को नहीं बुला सकता है, उदाहरण के लिए:

 class Test { public: void f(); void g() const; }; Test ff(); Test const gg(); ff().f(); // legal ff().g(); // legal gg().f(); // **illegal** gg().g(); // legal 

आप स्पष्ट रूप से मान, पैरामीटर और फ़ंक्शन स्वयं वापस करने के लिए आवेदन करने के लिए उपयोग के बीच स्पष्ट रूप से अंतर करना चाहिए।

मूल्य लौटें

  • यदि फ़ंक्शन मूल्य से वापस आ जाता है , तो const कोई फर्क नहीं पड़ता, क्योंकि ऑब्जेक्ट की प्रतिलिपि वापस की जा रही है। हालांकि यह सी ++ 11 में शामिल होगा, इसमें शामिल चाल-अर्थशास्त्र शामिल होंगे।
  • यह मूलभूत प्रकारों के लिए भी कभी भी मामला नहीं करता है, क्योंकि वे हमेशा नकल करते हैं

const std::string SomeMethod() const पर विचार करें यह (std::string&&) फ़ंक्शन का उपयोग करने की अनुमति नहीं देगा, क्योंकि यह गैर-कॉन्स्ट रैवल्यू की अपेक्षा करता है दूसरे शब्दों में, लौटे हुए स्ट्रिंग को हमेशा प्रतिलिपि किया जाएगा।

  • यदि फ़ंक्शन संदर्भ द्वारा देता है , तो const ऑब्जेक्ट को संशोधित होने से बचाता है।

पैरामीटर

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

समारोह ही

  • यदि फ़ंक्शन अंत में const , तो यह केवल अन्य const फ़ंक्शंस चला सकता है, और क्लास डेटा के संशोधन को संशोधित या अनुमति नहीं दे सकता है। इस प्रकार, अगर यह संदर्भ द्वारा रिटर्न करता है, तो संदर्भ लौटाए जाने चाहिए const होना चाहिए केवल const फ़ंक्शंस को ऑब्जेक्ट या ऑब्जेक्ट के संदर्भ में कहा जा सकता है जो कि स्वयं को कॉन्फ़िगर करता है साथ ही अस्थिर क्षेत्रों को बदला जा सकता है।
  • कंपाइलर द्वारा बनाए गए व्यवहार ने this संदर्भ को T const* लिए बदल दिया है यह फ़ंक्शन हमेशा उसे const_cast कर सकता है, लेकिन निश्चित रूप से यह नहीं किया जाना चाहिए और असुरक्षित माना जाता है।
  • यह निश्चित रूप से केवल इस विनिर्देशक को क्लास के तरीकों पर प्रयोग करने योग्य है; अंत में const के साथ वैश्विक कार्य संकलन त्रुटि बढ़ाएगा।

निष्कर्ष

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

गैर-संदर्भ / गैर-सूचक रैवलुओं में const योग्यता जोड़ने में बहुत कम मूल्य है, और इसमें बिल्ट-इन को जोड़ने में कोई मतलब नहीं है

उपयोगकर्ता-परिभाषित प्रकारों के मामले में, एक const कॉल करने वाले ऑब्जेक्ट पर एक गैर- const सदस्य फंक्शन को लागू करने से रोक देगा। उदाहरण के लिए, दिए गए

 const std::string foo(); std::string bar(); 

फिर

 foo().resize(42); 

मना किया जाएगा, जबकि

 bar().resize(4711); 

अनुमति दी जाएगी

int तरह अंतर्निहित के लिए, यह बिल्कुल समझ में नहीं आता है, क्योंकि इस तरह के रैवल्यूज़ को वैसे भी संशोधित नहीं किया जा सकता है।

(मुझे याद है कि प्रभावी सी ++ operator=() का रिटर्न प्रकार operator=() एक संदर्भ संदर्भ बनाने पर चर्चा करता है, हालांकि, और इस पर विचार करना कुछ है।)


संपादित करें:

ऐसा लगता है कि स्कॉट ने वास्तव में यह सलाह दी थी । यदि हां, तो ऊपर दिए गए कारणों के कारण, मुझे सी ++ 98 और सी +0 03 के लिए भी संदेहास्पद लगता हैसी ++ 11 के लिए, मैं इसे स्पष्ट रूप से गलत मानता हूं , क्योंकि स्कॉट ने खुद को खोजा है प्रभावी सी ++, तृतीय संस्करण के लिए इरेटा में , वह लिखता है (या दूसरों की शिकायत करता है जिन्होंने शिकायत की है):

टेक्स्ट का अर्थ है कि सभी बाय-वैल्यू रिकॉन्स्ट const होनी चाहिए, लेकिन ऐसे मामलों में जहां गैर-कंस्ट्रेट-अल-रिटर्न का अच्छा डिज़ाइन अच्छा नहीं होता है, जैसे कि रिटर्न प्रकार std :: vector जहां कॉलर खाली सदिश के साथ स्वैप का इस्तेमाल करेंगे उन्हें प्रतिलिपि किए बिना वापसी मूल्य की सामग्री को "पकड़" करने के लिए

और बादमें:

उप-मूल्य फ़ंक्शन रिटर्न वैल्यू कंट्री घोषित करते हुए उन्हें C ++ 0x में रेव्यूव्यू रेफरेन्स तक बाध्य किया जायेगा। क्योंकि आरव्वेई संदर्भ सी ++ कोड की दक्षता में सुधार करने में मदद करने के लिए डिज़ाइन किए गए हैं, फ़ंक्शन हस्ताक्षर निर्दिष्ट करते समय कॉन्स्ट रिटर्न वैल्यू के इंटरैक्शन और रैवल्यू रेफरेंस के प्रारंभ को ध्यान में रखना महत्वपूर्ण है।

आप मेयेर्स की सलाह के बारे में सोच सकते हैं इस विधि के लिए const मॉडिफायर में आवश्यक अंतर है

यह एक गैर-कॉन्स्ट विधि है (अंत में कोई सूचना नहीं है) जिसका मतलब है कि उसे कक्षा की स्थिति को संशोधित करने की अनुमति है।

 int& operator[](const int index) 

यह एक एक const विधि है (अंत में सूचना const )

 const int operator[](const int index) const 

पैरामीटर और रिटर्न वैल्यू के प्रकारों के बारे में क्या, int और const int बीच एक मामूली अंतर है, लेकिन यह सलाह के बिंदु के लिए प्रासंगिक नहीं है। आपको क्या ध्यान देना चाहिए कि गैर-संवेदी अधिभार देता है int& इसका अर्थ है कि आप इसे आवंटित कर सकते हैं, उदा। num[i]=0 , और कॉन्स्ट अधिभार गैर-संशोधित मूल्य देता है (कोई बात नहीं अगर वापसी प्रकार int या const int )।

मेरी व्यक्तिगत राय में, यदि कोई ऑब्जेक्ट मूल्य से पारित हो जाता है , तो const मॉडिफ़र ज़रूरत से ज़्यादा ज़रूरी नहीं है। यह सिंटैक्स कम है और एक ही प्राप्त होता है

 int& operator[](int index); int operator[](int index) const; 

कॉन्स्ट के रूप में लौटने वाले मूल्यों का प्राथमिक कारण यह है कि आप foo() = 5; तरह कुछ नहीं कह सकते foo() = 5; । यह वास्तव में आदिम प्रकारों के साथ एक मुद्दा नहीं है, क्योंकि आप आदिम प्रकारों की संख्या को निर्दिष्ट नहीं कर सकते हैं, लेकिन उपयोगकर्ता-परिभाषित प्रकारों (जैसे (a + b) = c; के साथ एक ओवरलोडेड operator+ साथ एक मुद्दा है)

मैंने हमेशा के लिए औचित्य पाया है कि बजाय तलना आप ऐसे व्यक्ति को रोक नहीं सकते हैं जो अजीब कोड लिखने का इरादा रखता है, और इस विशेष प्रकार के बलात्कार का मेरी राय में कोई वास्तविक लाभ नहीं है

सी +11 के साथ, वास्तव में इस मुहावरे को नुकसान का एक अच्छा सौदा किया जा रहा है: कॉन्स्ट के रूप में मूल्य लौटने से अनुकूलन को रोकता है और जब भी संभव हो, इस प्रकार से बचा जाना चाहिए। असल में, अब मैं इसे एक विरोधी-पैटर्न पर विचार करूंगा।

सी ++ 11 के बारे में यहां एक गहनता से संबंधित लेख है

जब उस पुस्तक को लिखा गया था, तो सलाह थोड़ा कम थी, लेकिन उपयोगकर्ता को लिखने से रोकने के लिए, उदाहरण के लिए, foo() = 42; और यह कुछ लगातार बदलने के लिए उम्मीद है

operator[] के मामले में, यह थोड़ा भ्रामक हो सकता है यदि आप एक गैर- const अधिभार भी प्रदान नहीं करते हैं जो एक गैर-संदर्भ संदर्भ देता है, हालांकि आप संभवत: उस const संदर्भ या प्रॉक्सी ऑब्जेक्ट को लौटाने से उस भ्रम को रोक सकते हैं एक मूल्य का

इन दिनों, यह बुरी सलाह है, क्योंकि यह आपको नतीजे (गैर- const ) रैवल्यू संदर्भ को बाध्य करने से रोकता है।

(जैसा कि टिप्पणियों में बताया गया है, प्रश्न int तरह आदिम प्रकार लौटते समय मुहिम शुरू होता है, क्योंकि भाषा आपको ऐसे प्रकार की एक rvalue देने से रोकती है; मैं अधिक सामान्य मामले के बारे में बात कर रहा हूं जिसमें उपयोगकर्ता को परिभाषित किया गया है प्रकार के।)

आदिम प्रकारों (जैसे int ) के लिए, नतीजे की कॉन्स्ट-नेस कोई फर्क नहीं पड़ता। कक्षाओं के लिए, यह व्यवहार को बदल सकता है उदाहरण के लिए, आप अपने फ़ंक्शन के परिणाम पर एक गैर-कॉन्स्ट विधि कॉल करने में सक्षम नहीं हो सकते हैं:

 class Bigint { const C foo() const { ... } ... } Bigint b; b.foo().bar(); 

उपर्युक्त वर्जित है यदि bar() का एक const सदस्य कार्य C सामान्य में, जो भी समझ में आता है उसे चुनें।

उस पर गौर करें:

 const int operator[](const int index) const 

बयान के अंत पर const यह वर्णन करता है कि इस पद्धति को स्थिरांक कहा जा सकता है।

दूसरी ओर जब आप केवल लिखते हैं

 int& operator[](const int index) 

इसे केवल गैर-कॉन्स्ट उदाहरणों पर ही बुलाया जा सकता है और यह भी प्रदान करता है:

 big_int[0] = 10; 

वाक्य – विन्यास।

आपके अधिभार में से एक सरणी में एक आइटम के संदर्भ को लौट रहा है, जिसे आप बदल सकते हैं।

 int& operator[](const int index) { return _data[index]; } 

अन्य अधिभार आपके लिए उपयोग करने के लिए एक मूल्य लौटा रहा है।

 const int operator[](const int index) const { return _data[index]; } 

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

 int foo = myBigInt[1]; // Doesn't change values inside the object. myBigInt[1] = 2; // Assigns a new value at index ` 

सरणी-अनुक्रमणिका ऑपरेटर ( operator[] ) के उदाहरण में यह एक अंतर बना देता है

साथ में

 int& operator[](const int index) { /* ... */ } 

आप सरणी में प्रविष्टि को सीधे बदलने के लिए अनुक्रमण का उपयोग कर सकते हैं, उदाहरण के लिए इसे इस तरह से प्रयोग करना:

 mybigint[3] = 5; 

दूसरा, const int operator[](const int) ऑपरेटर का उपयोग केवल मूल्य लाने के लिए किया जाता है

हालांकि, फ़ंक्शन से रिटर्न वैल्यू के रूप में, साधारण प्रकार जैसे जैसे, यह कोई फर्क नहीं पड़ता जब यह मामला है, यदि आप अधिक जटिल प्रकार लौट रहे हैं, तो एक std::vector कहें, और std::vector को संशोधित करने के लिए फ़ंक्शन के कॉलर को नहीं चाहिए।

const रिटर्न टाइप यहां बहुत महत्वपूर्ण नहीं है चूंकि अस्थायी अस्थायी बदलने योग्य नहीं होते हैं, इसलिए int vs const int का उपयोग करने में कोई अंतर नहीं है। यदि आप एक अधिक जटिल ऑब्जेक्ट का उपयोग करते हैं, जिसे संशोधित किया जा सकता है तो आपको एक अंतर दिखाई देगा।

कुछ अच्छे उत्तर दो संस्करणों की तकनीकी के चारों ओर घूमते हैं। एक आदिम मूल्य के लिए, यह कोई फर्क नहीं पड़ता।

हालांकि , मैं हमेशा कंपाइलर के बजाय प्रोग्रामर के लिए const मानता हूं। जब आप const लिखते हैं, तो आप स्पष्ट रूप से कह रहे हैं कि "इसे बदलना नहीं चाहिए" चलो यह सामना करते हैं, आम तौर पर आम तौर पर const जा सकता है, सही है?

जब आप एक const वापसी करते हैं, तो आप उस प्रोग्रामर को बता रहे हैं जो उस फ़ंक्शन का उपयोग करता है जिसे मान को परिवर्तित नहीं किया जाना चाहिए। और अगर वह इसे बदल रहा है, तो शायद वह कुछ गलत कर रहा है, क्योंकि उसे / उसके पास नहीं होना चाहिए

संपादित करें: मुझे यह भी लगता है कि "जब भी संभव हो, const उपयोग करें" बुरा सलाह है आपको इसका उपयोग करना चाहिए जहां यह समझ में आता है