सी ++ कांस्टिट्यूशन एक्सप्लोरेशन


97
const int* const Method3(const int* const&) const;

क्या कोई प्रत्येक कांस्टेबल के उपयोग की व्याख्या कर सकता है?


27
मुझे वास्तव में जटिल घोषणाओं को समझने के लिए यह तरीका पसंद है: c-faq.com/decl/spiral.anderson.html
जेसन

जवाबों:


77

इसे पढ़ें: https://isocpp.org/wiki/faq/const-correctness

फाइनल का constमतलब है कि फ़ंक्शन Method3अपने वर्ग के गैर-परिवर्तनशील सदस्यों को संशोधित नहीं करता है।

const int* constका अर्थ है एक स्थिर int का निरंतर सूचक: अर्थात ऐसा सूचक जिसे परिवर्तित नहीं किया जा सकता है, जिसे int में परिवर्तित नहीं किया जा सकता है: केवल इस और इसके बीच का अंतर const int&हैnull

const int* const&एक निरंतर सूचक के लिए एक स्थिर सूचक का संदर्भ है। आमतौर पर संकेत संदर्भ द्वारा पारित नहीं किए जाते हैं; const int* &अधिक समझ में आता है क्योंकि इसका मतलब यह होगा कि मेथड कॉल के दौरान पॉइंटर को बदला जा सकता है, जो एकमात्र कारण होगा जिसे मैं संदर्भ द्वारा पॉइंटर पास करने के लिए देख सकता हूं, const int* const&यह सभी इरादों और उद्देश्यों के समान है, const int* constसिवाय इसके कि यह शायद कम कुशल है संकेत सादे पुराने डेटा (POD) प्रकार के होते हैं और इन्हें सामान्य रूप से मूल्य द्वारा पारित किया जाना चाहिए।


104

यह समझना आसान है कि क्या आप इसे पूरी तरह से समकक्ष मानते हैं

// v───v───v───v───v───v───v───v───v───v───v───v─┬┐
//                                               ││
//  v──#1    v─#2             v──#3    v─#4      #5
   int const * const Method3(int const * const&) const;

फिर इसे दाईं से बाईं ओर पढ़ें।

# 5 कहता है कि बाईं ओर संपूर्ण फ़ंक्शन घोषणा है const, जिसका अर्थ है कि यह आवश्यक रूप से एक नि: शुल्क फ़ंक्शन के बजाय एक सदस्य फ़ंक्शन है।

# 4 कहता है कि बाईं ओर का पॉइंटर const(भिन्न पते पर इंगित करने के लिए नहीं बदला जा सकता है)।

# 3 कहता है कि intबाईं ओर const(भिन्न मान के लिए नहीं बदला जा सकता है)।

# 2 कहता है कि बाईं ओर सूचक है const

# 1 कहता है कि intबाईं ओर है const

यह सब एक साथ रखते हुए, आप इसे एक constसदस्य फ़ंक्शन के रूप में पढ़ सकते हैं जिसका नाम एक (या यदि आप पसंद करते हैं) के Method3लिए एक constपॉइंटर का संदर्भ लेता है और एक ( ) को एक पॉइंटर लौटाता है ।int constconst intconstint constconst int

(Nb # 2 पूरी तरह से बहुत बढ़िया है ।)


22

सबसे पहले के const Tबराबर है T const

const int* constइसलिए इसके बराबर है int const * const

जब constउनमें बहुत सारे टोकन और पॉइंटर्स के साथ भावों को पढ़ते हैं, तो हमेशा उन्हें दाएं से बाएं (ऊपर के परिवर्तन को लागू करने के बाद) पढ़ने की कोशिश करें । तो इस मामले में रिटर्न वैल्यू एक कॉस्टint को एक कॉन्सर्ट पॉइंटर है । पॉइंटर बनाना अपने आप में constकोई मतलब नहीं है क्योंकि रिटर्न वैल्यू एक ऐसा अंतराल नहीं है जिसे संशोधित किया जा सकता है। constहालाँकि, पॉइंटर बनाना इस बात की गारंटी देता है कि कॉलर द्वारा लौटाए गए int(या सरणी ऑफ intएस) को संशोधित नहीं किया जा सकता है Method3

const int*const&बन जाता है int const*const&, इसलिए यह एक कास्ट को एक पॉइंटर पॉइंटर का संदर्भ हैint । संदर्भ पुरुष द्वारा किसी भी पॉइंटर को पास करना कोई अर्थ नहीं है - आप पॉइंटर के बाद से रेफरेंस वैल्यू को संशोधित नहीं कर सकते हैं constऔर रेफरेंस और पॉइंटर्स समान स्टोरेज पर कब्जा कर लेते हैं इसलिए कोई स्पेस सेविंग भी नहीं है।

अंतिम constइंगित करता है कि विधि thisऑब्जेक्ट को संशोधित नहीं करती है। thisविधि शरीर के भीतर सूचक (सैद्धांतिक) घोषणा करनी होगी T const * const this। इसका मतलब है कि कोई const T*ऑब्जेक्ट कॉल करने में सक्षम होगा T::Method3()


2
इस (और ildjarn के समान उत्तर) को वोट करने के लिए, इस बात के लिए कि पूरी बात अधिक समझ में आती है यदि आप constवाक्यांश के सिर पर पहला एस नहीं डालते हैं । यह ठीक यही है कि मुझे क्यों लगता है constकि भाषा को अनुमति देना बुरा है , भले ही भाषा इसकी अनुमति देती हो, और यह सबसे आम उपयोग है।
TED

12

नियमों को याद रखने का एक आसान तरीका है, constइसके बारे में इस तरह से सोचना: यह constइसके बाईं ओर की बात पर लागू होता है, जब तक कि इसके बाईं ओर कुछ भी नहीं है।

तो const int * constपहले मामले में , इसके पहले हिस्से में कुछ भी नहीं बचा है, इसलिए यह लागू होता है intऔर दूसरा इसके बाईं ओर कुछ होता है, इसलिए यह पॉइंटर पर लागू होता है।

यह नियम आपको यह भी बताता है कि आपके पास उस मामले में क्या होगा const int const *। चूंकि intइस अभिव्यक्ति के लिए दोनों कास्ट निरर्थक है और इसलिए अमान्य है।


3
const /* don't modify the int or array of ints' value(s) */
int* const /* as a retval, ignored. useless declaration */
Method3(const /* don't modify the int or array of ints' value(s) */
int* const /* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */
&) const; /* this method does not modify the instance/object which implements the method */

3

मैं "घड़ी" या "सर्पिल" पद्धति का उपयोग करना पसंद करता हूं, जहां पहचानकर्ता नाम (इस मामले में Method3) से शुरू होता है जिसे आप डिकोड करने के लिए बाएं-से-दाएं-से-पीछे-पीछे आदि पढ़ते हैं। नामकरण की परंपरा। तो const int* const Method3(const int* const&) constएक वर्ग विधि है जो किसी भी वर्ग के सदस्यों (कुछ गैर-नामित वर्ग) को नहीं बदलता है और एक पॉइंटर के लिए एक निरंतर संदर्भ लेता है जो एक निरंतर को इंगित करता है intऔर एक स्थिर पॉइंटर को एक स्थिर पर लौटाता है int

उम्मीद है की यह मदद करेगा,

जेसन


2

C ++ में कास्ट को याद रखने का एक आसान तरीका यह है कि जब आपको कुछ कोड दिखाई देते हैं जैसे:

XXX const;
const YYY;

XXX, YYY एक निरंतर घटक, हो जाएगा
XXX constप्रपत्र:

function ( def var ) const;    ------#1
* const;                       ------#2

const YYY प्रपत्र:

const int;                     ------#3
const double;

लोग आमतौर पर इन प्रकारों का उपयोग करते हैं। जब आप "const&"कहीं देखते हैं , तो उलझन महसूस नहीं करते हैं, कास्ट खुद से पहले कुछ का वर्णन कर रहा है। इसलिए इस समस्या का जवाब अब स्पष्ट है।

const int* const Method3(const int* const&) const;
  |          |             |          |       |
  #3         #2            #3         #2      #1

2

मैं केवल यह बताना चाहता हूं कि const int* const&वास्तव में यह एक निरंतर संदर्भ है const int*। उदाहरण के लिए:

int i = 0;
int j = 1;
int* p = &i;
int* q = &j;
const int* const& cpref = p;
cpref = q; //Error: assignment of read-only reference 'cpref'

यह भी मामला है int* const&, जिसका अर्थ है: "एक निरंतर संदर्भ int*"।
लेकिन const int*&एक गैर-स्थिर संदर्भ है const int*
उम्मीद है की यह मदद करेगा।


1

दाएं से बाएं पढ़ने से मॉडिफायर को समझना आसान हो जाता है।

एक कांस्ट विधि जो एक कॉन्स्टेंट पॉइंटर को एक कॉन्स्टेंट इंट को संदर्भित करती है जिसे कहा जाता है Method3जो एक कॉन्सटर पॉइंटर को एक कॉन्टेस्ट इंट में लौटाता है।

  1. एक कास्ट विधि सदस्यों को संशोधित नहीं कर सकती (जब तक कि वे स्पष्ट रूप से न हों mutable)
  2. एक कॉन्स्टेंट पॉइंटर को किसी और चीज़ की ओर इशारा नहीं किया जा सकता है
  3. एक कास्ट इंट (या किसी अन्य प्रकार) को संशोधित नहीं किया जा सकता है

1

const # 1: Method3 द्वारा दिया गया पॉइंटर एक const int को संदर्भित करता है।

const # 2: सूचक मान फ़ंक्शन द्वारा लौटाया गया, स्वयं, const है। यह एक बेकार कास्ट (हालांकि ग्राम्य रूप से मान्य) है, क्योंकि किसी फ़ंक्शन से वापसी मान एल-वैल्यू नहीं हो सकता है।

const # 3: पॉइंटर प्रकार फ़ंक्शन के संदर्भ में एक कॉन्स्टेंट इंट को इंगित करता है।

const # 4: फ़ंक्शन के संदर्भ में दिया गया पॉइंटर मान, स्वयं, एक पॉइंटर पॉइंटर है। एक मान को घोषित करना जो एक फ़ंक्शन को कॉन्स्ट के रूप में पास किया जाता है, सामान्य रूप से व्यर्थ होगा, लेकिन यह मान संदर्भ द्वारा पारित किया जाता है, इसलिए यह सार्थक हो सकता है।

const # 5: फ़ंक्शन (संभवतः एक सदस्य फ़ंक्शन) कॉन्स्टेंस है, जिसका अर्थ है कि यह (ए) ऑब्जेक्ट के किसी भी सदस्य को नए मान प्रदान करने की अनुमति नहीं देता है, जिसमें वह हिस्सा है या (बी) एक गैर-कॉन्स्टेबल सदस्य फ़ंक्शन को कॉल करता है वस्तु या उसके किसी सदस्य पर।


0
  • const विधि के अंत में ऑब्जेक्ट के राज्य को इंगित करने वाला क्वालीफायर है जिसे बदला नहीं जा सकता है।

  • const int*const&एक कॉन्टेक्ट स्थान पर एक कॉइंटर पॉइंटर को संदर्भ द्वारा प्राप्त करने का संकेत देता है। यह न तो किसी अलग स्थान को इंगित करने के लिए बदल सकता है और न ही उस मूल्य को बदल सकता है जो इसे इंगित कर रहा है।

  • const int*const वापसी मूल्य है जो एक स्थिर स्थान के लिए एक स्थिर सूचक भी है।


0

इस अवधारणा को प्रदर्शित करने के लिए कुछ उदाहरण अच्छे हो सकते हैं, बेहतर इम्हो।

class TestClass
{
private:
   int iValue;
   int* oValuePtr;
   int& oValueRef;

public:
   int TestClass::ByValMethod1(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   int TestClass::ByValMethod2(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod3(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod4(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod5(const int Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue *cannot* be modified
      // Access through a const object
      iValue = Value;
      iValue += 1;

      // Return value *cannot* be modified
      // Access through a const object
      return ++iValue;
   }

   int& TestClass::ByRefMethod1(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int& TestClass::ByRefMethod2(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod3(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod4(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod5(const int& Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int* TestClass::PointerMethod1(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   int* TestClass::PointerMethod2(const int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr cannot be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod3(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // iValue can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod4(const int* Value)
   {
      // Value cannot be modified
      Value++;

      // oValuePtr *cannot* be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod5(const int* Value) const
   {
      // Value can be modified
      ++Value;

      // oValuePtr *cannot* be assigned
      // const int* to int* const
      // Access through a const object
      oValuePtr = Value;

      // oValuePtr *cannot* be modified
      // Access through a const object
      oValuePtr += 1;

      // Return value *cannot* be modified
      return ++oValuePtr;
   }
};

आशा है कि ये आपकी मदद करेगा!

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