पहले या बाद में कांस्टेबल?


145

शुरू करने के लिए आप शायद जानते हैं कि constइसका उपयोग किसी वस्तु के डेटा या पॉइंटर को बदलने योग्य या दोनों के लिए नहीं किया जा सकता है।

const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer

हालाँकि आप सिंटैक्स का भी उपयोग कर सकते हैं:

Object const *obj; // same as const Object* obj;

केवल एक चीज जो प्रतीत होती है, वह है कि आप किस constकीवर्ड को डालते हैं । व्यक्तिगत रूप से मैं constटाइप करने के लिए बाईं ओर रखना पसंद करता हूं यह निर्दिष्ट करने के लिए डेटा परिवर्तनीय नहीं है क्योंकि मुझे लगता है कि यह मेरे बाएं से दाएं मानसिकता में बेहतर पढ़ता है लेकिन कौन सा वाक्यविन्यास पहले आया था?

इससे भी महत्वपूर्ण बात यह है कि constडेटा को निर्दिष्ट करने के दो सही तरीके क्यों हैं और आप किसी भी स्थिति में किसी एक को पसंद करेंगे या किसी अन्य की आवश्यकता होगी?

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

तो ऐसा लगता है कि यह एक मनमाना निर्णय था जब कंपाइलरों को चीजों की व्याख्या करने के मानक को मेरे जन्म से बहुत पहले ही तैयार कर लिया गया था। चूँकि constकीवर्ड के बाईं ओर क्या लागू होता है (डिफ़ॉल्ट रूप से?) मुझे लगता है कि उन्हें लगा कि कीवर्ड को लागू करने के लिए "शॉर्टकट" को जोड़ने में कोई बुराई नहीं है और कम से कम अन्य तरीकों से क्वालिफायर टाइप करें, जब तक कि घोषणा बदल नहीं जाती पार्सिंग एक * या ...

यह सी में भी मामला था तो मैं मान रहा हूं?


9
मैक्रो में हमेशा जोड़ने const के बाद , प्रकार जैसे #define MAKE_CONST(T) T constबजाय #define MAKE_CONST(T) const Tइतना है कि MAKE_CONST(int *)सही ढंग से करने के लिए विस्तार होगा int * constबजाय const int *
जोटिक

6
मैंने इन दो शैलियों को "पूर्व कास्ट" और "पश्चिम कास्ट" के रूप में संदर्भित देखा है।
टॉम एंडरसन

13
@TomAnderson लेकिन वास्तव में यह "पूर्व कांस्टेबल" और "कास्ट वेस्ट" होना चाहिए।
YSC

जवाबों:


96

constडेटा को निर्दिष्ट करने के दो सही तरीके क्यों हैं और यदि आप किसी भी स्थिति में किसी एक को पसंद करेंगे या किसी को किस स्थिति में आवश्यकता होगी?

अनिवार्य रूप से, कारण यह है कि constतारांकन से पहले विनिर्देशक के भीतर की स्थिति मायने नहीं रखती है कि सी व्याकरण को कार्निघन और रिची द्वारा इस तरह से परिभाषित किया गया था।

इस कारण से उन्होंने व्याकरण को इस तरह परिभाषित किया कि संभावना है कि उनके सी संकलक ने बाएं से दाएं और इनपुट से प्रत्येक टोकन को संसाधित किया, क्योंकि यह उपभोग करता था। *टोकन की खपत वर्तमान घोषणा की स्थिति को सूचक प्रकार में बदल देती है। सामना constके बाद *साधन constक्वालीफायर एक सूचक घोषणा करने के लिए लागू किया जाता है; *क्वालीफायर को इंगित किए गए साधनों से पहले इसका सामना करना पड़ता है।

क्योंकि अर्थ अर्थ बदल नहीं जाता है अगर const क्वालिफायर टाइप स्पेसर के पहले या बाद में प्रकट होता है, तो इसे किसी भी तरह से स्वीकार किया जाता है।

फ़ंक्शन पॉइंटर्स की घोषणा करते समय इसी तरह का मामला सामने आता है, जहां:

  • void * function1(void)एक समारोह की घोषणा करता है void *, जो लौटता है ,

  • void (* function2)(void)एक फ़ंक्शन को एक फ़ंक्शन पॉइंटर घोषित करता है जो वापस लौटता है void

फिर से ध्यान देने वाली बात यह है कि लैंग्वेज सिंटैक्स लेफ्ट-टू-राइट पार्सर का समर्थन करता है।


7
कर्निघन ने किताब का सह-लेखन किया लेकिन सी के डिजाइन में शामिल नहीं थे, सिर्फ रिची।
टॉम ज़िक

8
मुझे कभी याद नहीं रहा कि कौन सा कौन सा है। आपके स्पष्टीकरण के लिए धन्यवाद, मुझे अंततः इसे याद रखने के लिए mnemotechnic है। धन्यवाद! *संकलक पार्सर से पहले नहीं जानता कि यह सूचक है इस प्रकार यह डेटा मूल्य के लिए कास्ट है। * के बाद यह निरंतर सूचक से संबंधित है। प्रतिभाशाली। और अंत में यह बताता है कि क्यों मैं क्या कर सकते हैं const charऔर साथ ही char const
विट बर्नाटिक

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

3
"क्योंकि शब्दार्थक अर्थ नहीं बदलता है यदि कास्ट क्वालीफ़ायर टाइप स्पेसर के पहले या बाद में प्रकट होता है, तो इसे किसी भी तरह से स्वीकार किया जाता है।" कि परिपत्र तर्क नहीं है? सवाल यह है कि शब्दार्थ अर्थ को इस तरह परिभाषित किया गया है, इसलिए मुझे नहीं लगता कि यह वाक्य कुछ भी योगदान देता है।
डॉन हैच

1
@donhatch आपको यह याद रखना होगा कि, आज के सापेक्ष और मान्यताओं को हम अच्छी प्रोग्रामिंग भाषा डिजाइन के साथ अपनी परिचितता के आधार पर बनाते हैं, भाषाएं तब बहुत नई चीजें थीं। इसके अलावा, क्या किसी के पास एक अनुमति या प्रतिबंधित भाषा एक मूल्य निर्णय है। जैसे, अजगर को एक ++ऑपरेटर चाहिए ? "वाक्य", इम्हो, ने मुझे एहसास दिलाया कि वहाँ कोई विशेष कारण नहीं था क्योंकि वे कर सकते थे। शायद वे आज एक अलग पसंद करेंगे / शायद नहीं।
ragerdl

75

नियम है:

const इसे छोड़ दी गई चीज़ पर लागू होता है। यदि बाईं ओर कुछ भी नहीं है, तो यह उस पर दाईं ओर लागू होता है।

मैं कांस्ट होने के लिए चीज़ के दाईं ओर कास्ट का उपयोग करना पसंद करता हूं क्योंकि यह "मूल" तरीका है जिसे कॉन्स्ट परिभाषित किया गया है।

लेकिन मुझे लगता है कि यह बहुत ही व्यक्तिपरक दृष्टिकोण है।


18
मैं इसे बाईं ओर रखना पसंद करता हूं, लेकिन मुझे लगता है कि इसे दाईं ओर रखना अधिक मायने रखता है। आप आमतौर पर C ++ में राइट-टू-लेफ्ट से टाइप पढ़ते हैं, उदाहरण के Object const *लिए एक कास्ट ऑब्जेक्ट के लिए एक पॉइंटर है। यदि आप constबाईं ओर रखते हैं, तो यह एक ऑब्जेक्ट के लिए एक संकेतक के रूप में पढ़ा जाएगा जो कि कास्ट है, जो वास्तव में बहुत अच्छी तरह से प्रवाह नहीं करता है।
Collin Dauphinee

1
मैं इस धारणा के तहत हूँ कि बाईं ओर सी-डिक्लेरेशन के अन्य प्रकार के साथ मानव-शैली की संगति है (कंप्यूटर-वार यह सही नहीं है क्योंकि constयह स्टोरेज क्लास नहीं है, लेकिन लोग पार्सर नहीं हैं)।
गीकौसोर

1
@ मुझे विश्वास है कि यह एक नियम से अधिक दिशानिर्देश है और मैंने इसे अक्सर यह याद रखने के तरीके के रूप में सुना है कि संकलक इसकी व्याख्या कैसे करेगा ... मैं समझता हूं कि यह कैसे काम करता है इसलिए मैं केवल विचार प्रक्रिया के पीछे उत्सुक था इसे दोनों तरीकों से समर्थन करने का निर्णय।
AJG85

3
@HeathHunnicutt नियम मौजूद है, लेकिन यह अभी थोड़ा अधिक जटिल है: c-faq.com/decl/spiral.anderson.html
imallett

2
@HHHHnicnic: सर्पिल नियम पहले टिप्पणीकार की टिप्पणी का विस्तारित संस्करण है "आप आमतौर पर राइट-टू-लेफ्ट से [C /] C ++ में टाइप पढ़ते हैं"। मैंने मान लिया कि आप इसका खंडन कर रहे हैं। हालाँकि, मुझे लगता है कि आप इसके बजाय उत्तर का उल्लेख कर रहे होंगे।
imallett

57

मैं दूसरा सिंटैक्स पसंद करता हूं। यह मुझे सही से बाएं प्रकार की घोषणा को पढ़कर 'क्या' का ट्रैक रखने में मदद करता है:

Object * const obj;        // read right-to-left:  const pointer to Object
Object const * obj;        // read right-to-left:  pointer to const Object
Object const * const obj;  // read right-to-left:  const pointer to const Object

3
बिल्कुल सही। एक "एक स्थिर वस्तु के लिए निरंतर सूचक" है Object const* const, नहीं const const Object*। "कॉन्स्ट" को विशेष मामले को छोड़कर बाईं ओर नहीं किया जा सकता है जहां इतने सारे लोग इसे पूरी तरह से प्यार करते हैं। (ऊपर हीथ देखें।)
cdunn2001

38

एक घोषणा में खोजशब्दों का क्रम यह सब तय नहीं है। "एक सही आदेश" के कई विकल्प हैं। ऐशे ही

int long const long unsigned volatile i = 0;

या यह होना चाहिए

volatile unsigned long long int const i = 0;

??


25
एक साधारण चर की पूरी तरह से भ्रमित परिभाषा के लिए +1। :)
Xio

@rubenvb - हाँ, दुर्भाग्य से वे हैं। व्याकरण सिर्फ इतना कहता है कि एक decl-specifier-seqका अनुक्रम है decl-specifier। व्याकरण द्वारा कोई आदेश नहीं दिया गया है, और प्रत्येक कीवर्ड के लिए होने वाली संख्या केवल कुछ शब्दार्थ नियमों द्वारा सीमित है (आप एक हो सकते हैं constलेकिन दो long:-)
बो पर्सन

3
@rubenvb - हां, unsignedएक प्रकार है, जैसा कि unsigned intऔर जैसा है int unsignedunsigned longएक और प्रकार है, जैसा कि unsigned long intऔर जैसा है int long unsigned। पैटर्न देखें?
बो पर्सन

2
@ कोई बात नहीं: मैं एक पैटर्न को देखने के लिए तीन है ;)। ठीक है, धन्यवाद
19:53

1
आप staticशब्दों की गड़बड़ी में शामिल होने में सक्षम थे , लेकिन हाल ही में कंपाइलरों ने शिकायत की है कि staticपहले आने की जरूरत है।
मार्क लाटा

8

पहला नियम यह है कि जो भी आपके स्थानीय कोडिंग मानकों की आवश्यकता हो प्रारूप का उपयोग करे। उसके बाद: constसामने की ओर लगाने से भ्रम की स्थिति खत्म नहीं होती है, जब टाइपफेड शामिल होते हैं, जैसे:

typedef int* IntPtr;
const IntPtr p1;   // same as int* const p1;

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


मुझे लगता है कि इस कारण पर प्रकाश डाला जा सकता है कि हमारे पास इस दुकान पर अपने निर्धारित मानकों के अनुसार क्यों नहीं इंगित करने वाले टाइपर्स हैं।
AJG85

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

आह हां, मैं const std::string::const_iteratorअच्छे उपाय के लिए व्यवहार को शामिल कर सकता था ;)
AJG85

2
@JamesKanze - एक मिनट रुको, मेरी मदद करो यहाँ ... मैं पोस्ट किए गए उदाहरण में भ्रम नहीं देखता। const IntPtr p1"निरंतर पूर्णांक सूचक" (यानी, "पूर्णांक के लिए निरंतर सूचक") के अलावा और क्या हो सकता है? कोई भी उनके सही दिमाग में नहीं है, यहां तक ​​कि बिना यह जाने कि कैसे IntPtrपरिभाषित किया गया है, यह सोचेंगे कि p1यह परिवर्तनशील है। और उस मामले के लिए, कोई भी गलत तरीके से क्यों मान लेगा जो *p1अपरिवर्तनीय है? और क्या है, कहीं और भी (जैसे IntPtr const p1) कास्ट लगाकर, शब्दार्थ को बिल्कुल नहीं बदला।
टॉड लेहमन

3
@ToddLehman आप भ्रम को नहीं देख सकते हैं, लेकिन अधिकांश C ++ प्रोग्रामर करते हैं, और व्यवस्थित रूप से इसे गलत पाते हैं (कोई संदेह नहीं कि चीजों से मदद मिलती है std::vector<T>::const_iterator, जहां यह इट्रेटर नहीं है जो कि कॉन्स्ट है, लेकिन यह क्या इंगित कर रहा है)।
जेम्स कंज

7

ऐसे ऐतिहासिक कारण हैं जो या तो बाएं या दाएं स्वीकार्य हैं। स्ट्रॉस्ट्रुप ने 1983 तक C ++ में कास्ट को जोड़ दिया था दिया था, लेकिन C89 / C90 तक यह C से नहीं बना।

C ++ में हमेशा दाईं ओर const का उपयोग करने का एक अच्छा कारण है। आप सभी जगह सुसंगत रहेंगे, क्योंकि कास्ट सदस्य कार्यों को इस तरह घोषित किया जाना चाहिए:

int getInt() const;

1
... ठीक है, "अच्छा कारण" इतना ठोस नहीं है, क्योंकि "कॉन्स्ट" के लिए अन्य संभावित स्थानों का मतलब एक ही बात नहीं होगा। const int& getInt(); int& const getInt();
मेस्ट्रो

1
@ मैस्ट्रो: मैं सुझाव दे रहा हूं कि यह int const& getInt();समकक्ष से बेहतर है, const int& getInt();जबकि int& const getInt();आप इसकी तुलना बेमानी है (संदर्भ पहले ही कास्ट हैं) हालांकि कानूनी और आमतौर पर एक चेतावनी देगा। वैसे भी, एक मेम्बर फंक्शन पर कास्ट, फंक्शन में thisपॉइंटर को से बदल देता Foo* constहै Foo const* const
निक वेस्टगेट

constएक सदस्य समारोह में सभी एक ही बात पर मतलब नहीं है - या void set(int)&;एक समारोह के संदर्भ के कुछ प्रकार है?
डेविस हेरिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.